package com.zmn.oms.zmn.aop;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.zmn.base.engineer.common.dro.foreign.engineer.ForeignEngineerDetailInfoDRO;
import com.zmn.base.engineer.dubbo.interfaces.engineer.cooperate.EngineerCooperateInfoListRemoteService;
import com.zmn.base.engineer.dubbo.interfaces.foreign.EngineerListRemoteService;
import com.zmn.common.constant.FicoConsts;
import com.zmn.common.dictionary.GlobalDict;
import com.zmn.common.dto.pay.RefundResultDTO;
import com.zmn.common.dto2.Option;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.amount.AmountUtil;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.math.MathUtil;
import com.zmn.common.utils.math.MoneyUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.dms.common.enums.coup.ThirdPlatEnum;
import com.zmn.manager.mq.constant.MqTopicConsts;
import com.zmn.manager.mq.interfaces.ZmnMQSender;
import com.zmn.oms.business.interfaces.base.BaseCodeService;
import com.zmn.oms.business.interfaces.eventsnotice.EventsNoticeBService;
import com.zmn.oms.business.interfaces.log.OrderLogBService;
import com.zmn.oms.business.interfaces.log.OrderLogNodeNoticeBService;
import com.zmn.oms.business.interfaces.log.OrderLogOperateRecordBService;
import com.zmn.oms.business.interfaces.log.OrderRedistributeLogBService;
import com.zmn.oms.business.interfaces.orderstock.OrderStockBService;
import com.zmn.oms.business.interfaces.part.OrderPartBService;
import com.zmn.oms.business.interfaces.work.OrderWorkBService;
import com.zmn.oms.business.interfaces.work.OrderWorkPositionBService;
import com.zmn.oms.business.interfaces.xno.OrderXnoBindService;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.dio.quotation3.*;
import com.zmn.oms.common.dro.orderpay.OrderPayResultDRO;
import com.zmn.oms.common.dto.MapDTO;
import com.zmn.oms.common.dto.OmsBaseOperator;
import com.zmn.oms.common.dto.OmsOperator;
import com.zmn.oms.common.enums.MasterStockTypeEnum;
import com.zmn.oms.common.enums.RefundTypeEnum;
import com.zmn.oms.common.utils.MobileUtil;
import com.zmn.oms.common.vo.KVDict;
import com.zmn.oms.manager.utils.OmsMqTagConsts;
import com.zmn.oms.model.bo.order.OrderBO;
import com.zmn.oms.model.bo.work.discount.UseTimesCoupBO;
import com.zmn.oms.model.bo.work.review.RefundReviewBO;
import com.zmn.oms.model.dto.OrderExtendDTO;
import com.zmn.oms.model.dto.acceptance.OrderWorkAcceptanceDTO;
import com.zmn.oms.model.dto.call.CallSyncOrderDTO;
import com.zmn.oms.model.dto.changerecord.*;
import com.zmn.oms.model.dto.comment.OrderCommentDTO;
import com.zmn.oms.model.dto.comment.ZsCommentRemarkDTO;
import com.zmn.oms.model.dto.completecode.CompleteCodeDTO;
import com.zmn.oms.model.dto.fcorderpart.OrderFactoryPartDTO;
import com.zmn.oms.model.dto.finalprice.RefundDifferenceDTO;
import com.zmn.oms.model.dto.invoice.OrderInvoiceDTO;
import com.zmn.oms.model.dto.log.CallRecordLogDTO;
import com.zmn.oms.model.dto.master.MasterSharingDTO;
import com.zmn.oms.model.dto.master.SharingInfo;
import com.zmn.oms.model.dto.member.OrderMemberMasterReviewDTO;
import com.zmn.oms.model.dto.member.OrderMemberPlatReviewDTO;
import com.zmn.oms.model.dto.order.NonClaimOrderDTO;
import com.zmn.oms.model.dto.order.OrderDTO;
import com.zmn.oms.model.dto.order.OrderOperationFailMessage;
import com.zmn.oms.model.dto.order.pay.DuplicatePayRefundDTO;
import com.zmn.oms.model.dto.order.photo.OrderPhotoDetectionDTO;
import com.zmn.oms.model.dto.order.zmn.FactoryNewOrderPartDIO;
import com.zmn.oms.model.dto.order.zmn.ZsNormalCompensateWorkDTO;
import com.zmn.oms.model.dto.order.zmn.ZsNormalRefundWorkDTO;
import com.zmn.oms.model.dto.orderattachment.ModifyOrderAttachmentDTO;
import com.zmn.oms.model.dto.part.*;
import com.zmn.oms.model.dto.remark.OrderRemarkDetailDTO;
import com.zmn.oms.model.dto.remind.RemindDTO;
import com.zmn.oms.model.dto.serviceitem.AddOrderServiceItemDTO;
import com.zmn.oms.model.dto.tmall.OrderTmallExtendDTO;
import com.zmn.oms.model.dto.track.OrderTrackDTO;
import com.zmn.oms.model.dto.track.OrderTrackDetailDTO;
import com.zmn.oms.model.dto.work.compensate.CompensateDTO;
import com.zmn.oms.model.dto.work.compensate.CompensateReviewDTO;
import com.zmn.oms.model.dto.work.compensate.RemitVoucherDTO;
import com.zmn.oms.model.dto.work.masterwork.*;
import com.zmn.oms.model.dto.work.modify.*;
import com.zmn.oms.model.dto.work.modify.amount.*;
import com.zmn.oms.model.dto.work.modify.must.*;
import com.zmn.oms.model.dto.work.modify.other.ZsPartReimburseDTO;
import com.zmn.oms.model.dto.work.modify.other.ZsPartReimburseGroupDTO;
import com.zmn.oms.model.dto.work.modify.other.ZsRemarkDTO;
import com.zmn.oms.model.dto.work.orderpay.CancelPayDTO;
import com.zmn.oms.model.dto.work.refund.*;
import com.zmn.oms.model.dto.work.xno.TempXnoBindDTO;
import com.zmn.oms.model.dto.work.xno.TempXnoUnBindDTO;
import com.zmn.oms.model.dto.work.xno.XnoBindDTO;
import com.zmn.oms.model.dto.work.xno.XnoUnBindDTO;
import com.zmn.oms.model.entity.acceptance.OrderWorkAcceptance;
import com.zmn.oms.model.entity.changerecord.OrderChangeRecord;
import com.zmn.oms.model.entity.conf.attachment.ConfOrderAttachmentCategory;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.discount.OrderDiscount;
import com.zmn.oms.model.entity.enterpriseWeChat.EnterpriseWeChatLog;
import com.zmn.oms.model.entity.factory.OrderFactory;
import com.zmn.oms.model.entity.fcorderpart.FcOrderOldPartReturn;
import com.zmn.oms.model.entity.fcorderpart.FcOrderPartReview;
import com.zmn.oms.model.entity.fcorderpart.OrderFactoryPart;
import com.zmn.oms.model.entity.log.OrderLog;
import com.zmn.oms.model.entity.nonstandard.OrderNonstandard;
import com.zmn.oms.model.entity.order.OrderExtend;
import com.zmn.oms.model.entity.orderattachment.OrderAttachment;
import com.zmn.oms.model.entity.part.OrderPart;
import com.zmn.oms.model.entity.pay.OrderPay;
import com.zmn.oms.model.entity.post.OrderPost;
import com.zmn.oms.model.entity.product.OrderProduct;
import com.zmn.oms.model.entity.review.OmsOrderReview;
import com.zmn.oms.model.entity.serviceitem.OrderServiceItem;
import com.zmn.oms.model.entity.tag.OrderTag;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkLogChange;
import com.zmn.oms.model.vo.remark.OrderRemarkDetailVO;
import com.zmn.oms.model.vo.serviceitem.ServiceItemVO;
import com.zmn.oms.model.vo.work.detail.ZsXnoBindVO;
import com.zmn.oms.services.interfaces.changerecord.OrderChangeRecordService;
import com.zmn.oms.services.interfaces.changerecord.OrderServiceItemChangeRecordService;
import com.zmn.oms.services.interfaces.conf.attachment.ConfOrderAttachmentCategoryService;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.discount.OrderDiscountService;
import com.zmn.oms.services.interfaces.express.OrderPostService;
import com.zmn.oms.services.interfaces.factory.OrderFactoryService;
import com.zmn.oms.services.interfaces.order.OrderChangeService;
import com.zmn.oms.services.interfaces.order.OrderExtendService;
import com.zmn.oms.services.interfaces.order.OrderService;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.oms.services.interfaces.review.OmsOrderReviewService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.third.haobai.HaobaiConsts;
import com.zmn.oms.third.hb114.Haobai114Consts;
import com.zmn.oms.third.pinduoduo.util.PinDuoDuoUtil;
import com.zmn.oms.third.zhimi.ZhimiConsts;
import com.zmn.oms.zmn.business.interfaces.message.SendOrderNodeMsgService;
import com.zmn.oms.zmn.business.interfaces.work.ZsOrderWorkOperatePermissionBService;
import com.zmn.oms.zmn.business.interfaces.work.customwork.ZsDistributeWorkBService;
import com.zmn.pay.common.constant.PayConsts;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.aspectj.lang.ProceedingJoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：日志记录
 *
 * @author lujia
 * @date 2018/12/04 20:59
 */
public class OrderWorkBaseLogAspect {

    Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    OrderService orderService;

    @Autowired
    OrderDetailService orderDetailService;

    @Autowired
    OrderProductService orderProductService;

    @Autowired
    OrderFactoryService orderFactoryService;

    @Autowired
    OrderWorkService orderWorkService;

    @Autowired
    OrderLogBService orderLogBService;

    @Autowired
    OrderChangeService orderChangeService;

    @Autowired
    OrderWorkPositionBService orderPositionBService;

    @Autowired
    BaseCodeService baseCodeService;
    @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    EngineerListRemoteService engineerListRemoteService;
    // @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    //private EngineerProductGroupListRemoteService engineerProductGroupListRemoteService;

    @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    private EngineerCooperateInfoListRemoteService engineerCooperateInfoListRemoteService;
    @Resource
    ZmnMQSender zmnMQSender;

    @Autowired
    ZsOrderWorkOperatePermissionBService zsOrderWorkOperatePermissionBService;

    @Autowired
    OrderWorkBService orderWorkBService;

    @Autowired
    OrderXnoBindService orderXnoBindService;

    @Autowired
    OrderLogNodeNoticeBService orderLogNodeNoticeBService;

    @Autowired
    SendOrderNodeMsgService sendOrderNodeMsgService;

    @Autowired
    OrderLogOperateRecordBService orderLogOperateRecordBService;

    @Autowired
    private OrderExtendService orderExtendService;

    @Autowired
    private ConfOrderAttachmentCategoryService confOrderAttachmentCategoryService;

    @Autowired
    private OrderPartBService orderPartBService;

    @Autowired
    private OrderPostService orderPostService;

    @Autowired
    private OrderDiscountService orderDiscountService;

    @Autowired
    private OrderChangeRecordService orderChangeRecordService;

    @Autowired
    private OrderServiceItemChangeRecordService orderServiceItemChangeRecordService;

    @Autowired
    private ZsDistributeWorkBService zsDistributeWorkBService;

    @Autowired
    private OmsOrderReviewService orderReviewService;

    @Autowired
    private EventsNoticeBService eventsNoticeBService;

    @Autowired
    private OrderStockBService orderStockBService;

    @Autowired
    private OrderRedistributeLogBService orderRedistributeLogBService;

    Object doLog(ProceedingJoinPoint joinPoint, int logType, boolean beforeProceed, boolean handleLog)
            throws Throwable {

        // 工单操作参数
        OmsBaseOperator omsBaseOperator = (OmsBaseOperator) joinPoint.getArgs()[0];


        // 工单log
        OrderLog orderLog = new OrderLog();
        orderLog.setType(logType);
        orderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(logType));

        // 订单操作失败消息，当业务方法执行失败时使用
        OrderOperationFailMessage failMessage = new OrderOperationFailMessage();
        failMessage.setLogType(logType);
        failMessage.setOperatorId(orderLog.getOperatorId());
        failMessage.setOperatorName(orderLog.getOperator());
        failMessage.setOperatorType(orderLog.getOperatorType());
        failMessage.setExtra(omsBaseOperator.getExtra());

        // 查询工单
        OrderWork dbOrderWork = null;
        if (omsBaseOperator instanceof OmsOperator) {
            OmsOperator omsOperator = (OmsOperator) omsBaseOperator;
            if (omsOperator.getOrderId() != null && omsOperator.getWorkId() != null) {
                dbOrderWork = orderWorkService
                        .findOrderWorkByKeySrcMaster(omsOperator.getOrderId(), omsOperator.getWorkId());
            }
        }

        OrderWork newOrderWork = null;
        OrderDetail newOrderDetail = null;
        Object proceed;
        if (dbOrderWork == null) {

            // 新单处理
            proceed = joinPoint.proceed();
            if (proceed instanceof OrderBO) {
                OrderBO orderBO = (OrderBO) proceed;
                newOrderWork = orderBO.getOrderWork();
                newOrderDetail = orderBO.getOrderDetail();
                OrderWorkLogUtils.processNewOrderLog(orderBO, omsBaseOperator, orderLog);
            }
        } else {
            failMessage.setOrderId(dbOrderWork.getOrderId());
            failMessage.setWorkId(dbOrderWork.getWorkId());
            failMessage.setChannelId(dbOrderWork.getChannelId());
            failMessage.setOuterId(dbOrderWork.getOuterId());

            if (omsBaseOperator instanceof OrderDTO) {
                OrderDTO orderDTO = (OrderDTO) omsBaseOperator;
                newOrderWork = orderDTO.getOrderWork();
            }

            if (beforeProceed) {

                // 修改订单，获取日志
                if (handleLog) {
                    orderLog.setContent(
                            this.getLogContent(dbOrderWork, (OmsOperator) omsBaseOperator, orderLog, logType));
                } else {
                    orderLog.setContent(StringUtils.defaultString(omsBaseOperator.getOperatorRemark(),
                            omsBaseOperator.getOperatorLogRemark()));
                }

                // 后执行
                proceed = executJoinPoint(joinPoint, failMessage);
            } else {

                // 先执行
                proceed = executJoinPoint(joinPoint, failMessage);

                // 修改订单，获取日志
                if (handleLog) {
                    orderLog.setContent(
                            this.getLogContent(dbOrderWork, (OmsOperator) omsBaseOperator, orderLog, logType));
                } else {
                    orderLog.setContent(StringUtils.defaultString(omsBaseOperator.getOperatorLogRemark()));
                }
            }

            // 工单状态
            OrderWorkLogUtils.processOrderLogStatus(orderLog, dbOrderWork, (OmsOperator) omsBaseOperator);
        }

        // 操作人处理
        OrderWorkLogUtils.processOrderLogOperater(orderLog, omsBaseOperator, dbOrderWork);

        // 插入日志
        orderLogBService.save(orderLog);

        OrderExtend dbOrderExtend = null;
        try {
            // 检查是否存在用于同步订单的渠道扩展数据
            dbOrderExtend = orderExtendService.findMiniOrderExtendByOrderIdSrcMaster(orderLog.getOrderId());
        } catch (Exception e) {
        }

        // 返修原单log
        this.processReworkOrderLog(orderLog, newOrderWork);

        // 退款原单log
        this.processRefundOrderLog(orderLog, dbOrderWork);

        // 赔偿原单log
        this.processCompensateOrderLog(orderLog, dbOrderWork);

        // 预约失败
        this.processDutyFailOrderLog(orderLog, dbOrderWork, newOrderWork);

        // 保险单同步处理
        this.syncInsOrderProceed(orderLog, dbOrderWork, newOrderWork);

        // 订单同步处理
        this.syncOrderProceed(orderLog, dbOrderWork, newOrderWork, dbOrderExtend, omsBaseOperator);

        // 订单同步到呼叫
        this.syncCallProceed(Optional.ofNullable(dbOrderWork).orElse(newOrderWork), newOrderDetail, omsBaseOperator,
                logType);

        // 同步到数据上传
        this.syncUplaodIasc(orderLog, dbOrderWork);

        // 订单修改记录保存
        this.recordOrderChange(Optional.ofNullable(dbOrderWork).orElse(newOrderWork), omsBaseOperator, logType);

        // 服务项修改记录保存
        this.recordServiceItemChange(orderLog, dbOrderWork, newOrderWork);

        // 节点通知--绩效使用
        this.nodeNotice(orderLog, dbOrderWork, omsBaseOperator, proceed);

        // 节点通知--通用订阅
        eventsNoticeBService.notice(orderLog, dbOrderWork, newOrderWork, dbOrderExtend, omsBaseOperator, proceed);

        // 节点标签处理
        this.syncOrderTag(orderLog, dbOrderWork, newOrderWork, dbOrderExtend, omsBaseOperator, proceed);

        // 维护位置信息
        try {
            orderPositionBService.syncOrderPosition(dbOrderWork, omsBaseOperator, logType);
        } catch (Exception e) {
            logger.error("维护经纬度异常" + e.getMessage(), e);
        }

        // 订单消息通知处理
        this.sendOrderNodeMessage(orderLog, dbOrderWork, omsBaseOperator, proceed);

        // 安全监控
        this.sendOrderOperateRecord(orderLog, dbOrderWork, omsBaseOperator, proceed);

        // 改派申请取消处理
        this.sendCancelRedistributeApply(orderLog, dbOrderWork, omsBaseOperator, proceed);

        return proceed;
    }

    /**
     * 发送自动取消改派申请
     *
     * @param orderLog
     * @param omsBaseOperator
     */
    private void sendCancelRedistributeApply(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator, Object proceed) {
        if (!OrderWorkLogUtils.REDISTRIBUTE_APPLY_CANCEL_TYPE_LIST.contains(orderLog.getType())) {
            return;
        }
        orderRedistributeLogBService.noticeCancelRedistribute(orderLog, dbOrderWork, omsBaseOperator, proceed);
    }

    /**
     * 日志节点通知
     *
     * @param orderLog    订单日志
     * @param dbOrderWork
     * @param proceed
     */
    private void nodeNotice(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator, Object proceed) {
        orderLogNodeNoticeBService.notice(orderLog, dbOrderWork, omsBaseOperator, proceed);
    }

    /**
     * 订单标签处理
     *
     * @param orderLog        订单日志
     * @param omsBaseOperator
     * @param proceed
     */
    private void syncOrderTag(OrderLog orderLog,
                              OrderWork dbOrderWork,
                              OrderWork newOrderWork,
                              OrderExtend dbOrderExtend,
                              OmsBaseOperator omsBaseOperator,
                              Object proceed) {
        if (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_INPUT, orderLog.getType())
                || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_UPDATE, orderLog.getType())
                || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CONTACT_USER, orderLog.getType())
                || (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CONFIRM, orderLog.getType()) && !Objects.equals(orderLog.getOperatorType(), GlobalConsts.OPERATE_USER_TYPE_SYSTEM))
                || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE, orderLog.getType())
                || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_COMPLETE, orderLog.getType())
                || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CANCEL, orderLog.getType())
                || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_PAY, orderLog.getType())
                || (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CHECKOUT, orderLog.getType()) && Objects.equals(dbOrderWork.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE))
                || (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE_BACK, orderLog.getType()) && Objects.equals(dbOrderWork.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE))
                || (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_ASSIGN_BACK, orderLog.getType()) && Objects.equals(dbOrderWork.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE))
                || (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_REFUND_DIFFERENCE, orderLog.getType()))
        ) {

            Long orderId, workId;

            if (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_INPUT, orderLog.getType())) {
                orderId = newOrderWork.getOrderId();
                workId = newOrderWork.getWorkId();
            } else {
                orderId = omsBaseOperator.getOrderId();
                workId = omsBaseOperator.getWorkId();
            }

            String key = String.format("tag-%s-%s", workId, DateUtil.getNowTimestamp());
            JSONObject jb = new JSONObject();
            jb.put("orderId", orderId);
            jb.put("workId", workId);
            jb.put("logType", orderLog.getType());
            String content = jb.toJSONString();

            logger.info("订单标签同步队列， key:{}, content:{}", key, content);
            zmnMQSender.sendWithStartDeliverTime(MqTopicConsts.ZMN_TOPIC_OMS, MessageQueueTagConsts.ORDER_TAG, key, content, DateUtil.getNowTimestampMillis() + 1000);
        }
    }

    /**
     * 订单节点消息通知
     *
     * @param orderLog    订单日志
     * @param dbOrderWork
     * @param proceed
     */
    private void sendOrderNodeMessage(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator, Object proceed) {
        sendOrderNodeMsgService.notice(orderLog, dbOrderWork, omsBaseOperator, proceed);
    }

    /**
     * 安全监控
     *
     * @param orderLog    订单日志
     * @param dbOrderWork
     * @param proceed
     */
    private void sendOrderOperateRecord(OrderLog orderLog, OrderWork dbOrderWork, OmsBaseOperator omsBaseOperator, Object proceed) {
        orderLogOperateRecordBService.noticeRecord(orderLog, dbOrderWork, omsBaseOperator, proceed);
    }

    /**
     * 执行切面中实际的业务方法
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    private Object executJoinPoint(ProceedingJoinPoint joinPoint, OrderOperationFailMessage failMessage)
            throws Throwable {
        Object proceed = null;
        try {
            proceed = joinPoint.proceed();
        } catch (Throwable throwable) {
            //            failMessage.setOpTime(DateUtil.getNow());
            //            failMessage.setErrorMsg(throwable.getMessage());
            //            if (throwable instanceof OmsBaseException) {
            //                failMessage.setOmsBaseExceptionMsg(throwable.getMessage());
            //            }
            //            orderChangeService.orderOperationFailSyncToApi(failMessage);

            throw throwable;
        }

        return proceed;
    }

    // region 师傅按单保险

    /**
     * 订单同步判断处理
     *
     * @param orderLog     订单日志
     * @param dbOrderWork  旧单
     * @param newOrderWork 新单
     */
    void syncInsOrderProceed(OrderLog orderLog, OrderWork dbOrderWork, OrderWork newOrderWork) {
        OrderWork orderWork = Optional.ofNullable(dbOrderWork).orElse(newOrderWork);
        if (orderWork == null) {
            return;
        }

        boolean isSyncOrderType = Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)
                || Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_REWORK);

        if (!isSyncOrderType) {
            return;
        }

        // 领单（非家修匠订单）、上门（家修匠订单）、多工程师、完成、取消：给师傅买保险
        if (OrderWorkLogUtils.INS_OP_TYPE_LIST.contains(orderLog.getType())) {
            sendInsOrderMessage(orderLog);
            return;
        }
    }

    private void sendInsOrderMessage(OrderLog orderLog) {
        OrderWorkLogChange orderWorkLogChange = new OrderWorkLogChange();
        orderWorkLogChange.setLogType(orderLog.getType());
        orderWorkLogChange.setOrderId(orderLog.getOrderId());
        orderWorkLogChange.setWorkId(orderLog.getWorkId());
        orderWorkLogChange.setOpTime(DateUtil.getNow());
        orderChangeService.changeOfInsOrder(orderWorkLogChange);
    }
    // endregion

    /**
     * 订单同步
     *
     * @param orderLog
     * @param dbOrderWork
     * @param newOrderWork
     */
    private void syncOrderProceed(OrderLog orderLog,
                                  OrderWork dbOrderWork,
                                  OrderWork newOrderWork,
                                  OrderExtend dbOrderExtend,
                                  OmsBaseOperator omsBaseOperator) {
        OrderWork orderWork = Optional.ofNullable(dbOrderWork).orElse(newOrderWork);
        if (orderWork == null) {
            return;
        }

        // 只同步新单
        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return;
        }

        OrderWorkLogChange orderWorkLogChange = new OrderWorkLogChange();
        {
            orderWorkLogChange.setOperatorId(orderLog.getOperatorId());
            orderWorkLogChange.setOperatorName(orderLog.getOperator());
            orderWorkLogChange.setOperatorType(orderLog.getOperatorType());
            orderWorkLogChange.setLogType(orderLog.getType());
            orderWorkLogChange.setOrderId(orderLog.getOrderId());
            orderWorkLogChange.setWorkId(orderLog.getWorkId());
            orderWorkLogChange.setChannelId(orderWork.getChannelId());
            orderWorkLogChange.setInputType(orderWork.getInputType());
            orderWorkLogChange.setOuterId(orderWork.getOuterId());
            orderWorkLogChange.setStatus(orderLog.getAfterStatus());
            orderWorkLogChange.setResultStatus(orderLog.getAfterResultStatus());
            orderWorkLogChange.setOpTime(DateUtil.getNow());
            orderWorkLogChange.setServCategId(orderWork.getServCategId());
            orderWorkLogChange.setOrderSourceType(orderWork.getSourceType());
            orderWorkLogChange.setExtra(omsBaseOperator.getExtra());

            // 检查是否存在用于同步订单的渠道扩展数据
            if (dbOrderExtend != null && dbOrderExtend.getExtOuterData() != null) {
                orderWorkLogChange.setExtOuterData(dbOrderExtend.getExtOuterData());
            }
        }

        // 新单同步
        boolean syncNewOrder = false;
        if (dbOrderWork == null) {  // 新单
            Integer inputType = orderWork.getInputType();
            Integer channelId = newOrderWork.getChannelId();
            // 满足特定的录入类型
            if (OrderWorkLogUtils.SYNC_ORDER_NEW_TYPE_LIST.contains(inputType)) {
                syncNewOrder = true;
            }
            // 后台录入的特定渠道
            else if (OrderWorkLogUtils.SYNC_ORDER_NEW_CHANNEL_LIST.contains(channelId)) {
                syncNewOrder = true;
            } else if (PinDuoDuoUtil.isPinDuoDuoChannel(channelId)) {
                // 拼多多渠道新单同步
                syncNewOrder = true;
            }
        }

        // 查询同步给58的渠道
        boolean syncTo58 = baseCodeService.isChannelOrderSyncTo58(orderWork.getChannelId());

        if (syncNewOrder) {
            // 同步给渠道
            orderChangeService.newOrderSync(orderWorkLogChange);
            // 同步给渠道（新系统）
            orderChangeService.newOrderSyncToApi(orderWorkLogChange);
            // 自动确认的，同步给58
            if (syncTo58 && Objects.equals(OrderStatusConsts.WORK_STATUS_CONFIRM, orderLog.getAfterStatus())) {
                orderChangeService.changeStatusSyncTo58(orderWorkLogChange);
            }

            return;
        }

        if (Objects.equals(GlobalConsts.OPERATE_USER_TYPE_CHANNEL, orderLog.getOperatorType())) {

            // 渠道操作的取消，返回渠道取消事件消息（渠道操作取消，有可能是渠道申请退款，需回复渠道是否允许退款）
            if (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CANCEL, orderLog.getType())) {
                orderWorkLogChange.setLogType(OrderLogConsts.ORDER_LOG_TYPE_CHANNEL_CANCEL);
                orderChangeService.changeStatusSyncToApi(orderWorkLogChange);
                return;
            }

            // 非自动确认订单，不同步
            if (!Objects.equals(OrderStatusConsts.WORK_STATUS_CONFIRM, orderLog.getAfterStatus())) {
                return;
            }
        }

        // 智米订单：师傅修改产品需要发送通知事件，用于维护智米产品与智米订单服务类型的一致性
        if (Objects.equals(ZhimiConsts.CHANNEL_ID, orderWorkLogChange.getChannelId())
                && Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_MODIFY_PRODUCT, orderLog.getType())) {
            orderChangeService.changeStatusSyncToApi(orderWorkLogChange);
            return;
        }

        // 订单状态变更同步数据
        boolean syncToChannel = OrderWorkLogUtils.SYNC_ORDER_CHANGE_TYPE_LIST.contains(orderWork.getInputType());
        boolean syncHb114Channel = Haobai114Consts.isHaobai114SyncChannel(orderWorkLogChange.getChannelId()) && (
                Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CONFIRM, orderWorkLogChange.getLogType()) ||
                        Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_UPDATE, orderWorkLogChange.getLogType()) ||
                        Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_MASTER_MODIFY_DUTY_TIME, orderWorkLogChange.getLogType()));

        boolean syncToBaiduApp = (orderWorkLogChange.getChannelId() == OrderConsts.CHANNEL_ID_BAIDU_APP) ? true : false;
        boolean syncStatus = OrderWorkLogUtils.SYNC_ORDER_OP_TYPE_LIST.contains(orderLog.getType()) && (syncToChannel || syncTo58 || syncHb114Channel || syncToBaiduApp);

        // 厂商接入渠道独有的同步信息
        boolean isFactoryChannel = Objects.equals(orderWork.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_FACTORY);
        boolean syncType4Factory = isFactoryChannel && OrderWorkLogUtils.SYNC_ORDER_OP_TYPE_FACTORY_LIST.contains(orderLog.getType());

        boolean syncHaobai = (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_COMPLETE, orderWorkLogChange.getLogType()) || Objects
                .equals(OrderLogConsts.ORDER_LOG_TYPE_CANCEL, orderWorkLogChange.getLogType())) && HaobaiConsts
                .isHaobaiChannel(orderWorkLogChange.getChannelId());

        if (syncStatus) {
            // 新增、修改、确认， 未支付不推送状态
            if (OrderWorkLogUtils.SYNC_ORDER_OP_ADD_UPDATE_TYPE_LIST.contains(orderLog.getType())) {
                if (this.isWaitPrePay(orderWork)) {
                    return;
                }
            }

            // 修正渠道ID和服务类型
            if (newOrderWork != null) {
                orderWorkLogChange.setChannelId(newOrderWork.getChannelId());
                orderWorkLogChange.setServCategId(newOrderWork.getServCategId());
            }

            // 判断预约时间是否变化
            // 1.1 修改操作中修改预约时间
            if (dbOrderWork != null && newOrderWork != null) {
                Date newDutyTime = newOrderWork.getDutyTime();
                if (newDutyTime != null && DateUtil.toTimestampMillis(dbOrderWork.getDutyTime()) != DateUtil
                        .toTimestampMillis(newOrderWork.getDutyTime())) {
                    orderWorkLogChange.setDutyTime(newOrderWork.getDutyTime());
                }

                // 预约失败处理
                if (Objects.equals(OrderDutyConsts.DUTY_STATUS_FAIL, newOrderWork.getDutyStatus())
                        && newOrderWork.getNextContactTime() != null) {
                    orderWorkLogChange.setDutyStatus(newOrderWork.getDutyStatus());
                    orderWorkLogChange.setNextContactTime(newOrderWork.getNextContactTime());
                    orderWorkLogChange.setReasonCode(Objects.isNull(newOrderWork.getDutyFailCode()) ? GlobalConsts.NONE : newOrderWork.getDutyFailCode());
                }
            }
            // 1.2 工程师修改预约时间
            else if (omsBaseOperator instanceof ModifyDutyTimeDTO) {
                ModifyDutyTimeDTO modifyDutyTimeDTO = (ModifyDutyTimeDTO) omsBaseOperator;
                orderWorkLogChange.setDutyTime(modifyDutyTimeDTO.getDutyTime());
                orderWorkLogChange.setOperatorId(modifyDutyTimeDTO.getOperatorId());
            }

            // 同步挂起给天猫
            if (omsBaseOperator instanceof OrderWorkSuspendDTO) {
                if (Objects.equals(OrderConsts.CHANNEL_ID_TMALL_WYG, dbOrderWork.getChannelId()) ||
                        Objects.equals(OrderConsts.CHANNEL_ID_TMALL_QINGE_BW, dbOrderWork.getChannelId())) {
                    OrderWorkSuspendDTO orderWorkSuspendDTO = (OrderWorkSuspendDTO) omsBaseOperator;
                    orderWorkLogChange.setDutyStatus(OrderDutyConsts.DUTY_STATUS_SUSPEND);
                    orderWorkLogChange.setNextContactTime(orderWorkSuspendDTO.getNextContactTime());
                    orderWorkLogChange.setReasonCode(Objects.isNull(orderWorkSuspendDTO.getDutyFailCode()) ? GlobalConsts.NONE : orderWorkSuspendDTO.getDutyFailCode());
                }
            }

            // 派单操作，并且已支付，需要补推确认状态
            if (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE, orderLog.getType())) {
                if (Objects.equals(orderWork.getDisableDiscard(), GlobalConsts.YES) && !this.isWaitPrePay(orderWork)) {

                    OrderWorkLogChange confirmOrderWorkLogChange = BeanMapper
                            .map(orderWorkLogChange, OrderWorkLogChange.class);
                    confirmOrderWorkLogChange.setStatus(OrderStatusConsts.WORK_STATUS_CONFIRM);

                    // 同步给渠道
                    if (syncToChannel) {
                        orderChangeService.changeStatusSync(confirmOrderWorkLogChange);
                        orderChangeService.changeStatusSyncToApi(confirmOrderWorkLogChange);
                    } else if (syncHb114Channel || syncToBaiduApp) {
                        // 同步给 114渠道和百度小程序
                        orderChangeService.changeStatusSyncToApi(orderWorkLogChange);
                    }

                    // 同步给58
                    if (syncTo58) {
                        orderChangeService.changeStatusSyncTo58(confirmOrderWorkLogChange);
                    }
                }
            }
            // 完成操作，补充备注信息
            else if (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_COMPLETE, orderLog.getType())) {
                if (StringUtils.isNotBlank(orderLog.getContent())) {
                    orderWorkLogChange.setExtData(orderLog.getContent());
                }
            }

            // 同步给渠道-老平台
            if (syncToChannel) {
                orderChangeService.changeStatusSyncToApi(orderWorkLogChange);
                orderChangeService.changeStatusSync(orderWorkLogChange);
            } else if (syncHb114Channel || syncToBaiduApp) {
                // 同步给 114渠道和百度小程序
                orderChangeService.changeStatusSyncToApi(orderWorkLogChange);
            }

            // 同步给58
            if (syncTo58) {
                orderChangeService.changeStatusSyncTo58(orderWorkLogChange);
            }
        }
        // 不满足正常同步条件，再补充判断是否满足厂商同步条件
        else if (syncType4Factory) {
            // 同步厂商备注
            if (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_FACTORY_REMARK, orderLog.getType())
                    && StringUtils.isNotBlank(orderLog.getContent())
                    && StringUtils.isNotBlank(orderWorkLogChange.getOuterId())) {
                // 厂商备注内容
                orderWorkLogChange.setExtData(orderLog.getContent());
                orderChangeService.changeStatusSyncToApi(orderWorkLogChange);
            }
        } else if (syncHaobai) {
            orderChangeService.changeStatusSyncToApi(orderWorkLogChange);
        }

    }

    /**
     * 订单同步-呼叫系统
     *
     * @param orderWork
     * @param orderDetail
     * @param logType
     */
    private void syncCallProceed(OrderWork orderWork,
                                 OrderDetail orderDetail,
                                 OmsBaseOperator omsOperator,
                                 int logType) {

        // 只同步新订单和转单
        if (!OrderWorkLogUtils.SYNC_CALL_ORDER_TYPE_LIST.contains(logType)) {
            return;
        }

        if (orderWork == null) {
            return;
        }

        if (orderDetail == null) {
            orderDetail = orderDetailService.findOrderDetailByKey(orderWork.getOrderId());
            if (orderDetail == null) {
                return;
            }
        }

        // 转单的服务平台
        Integer platWork = orderWork.getPlatWork();
        if (OrderLogConsts.ORDER_LOG_TYPE_TURN == logType && omsOperator instanceof OrderTurnDTO) {
            OrderTurnDTO orderTurnDTO = (OrderTurnDTO) omsOperator;
            platWork = orderTurnDTO.getPlatWork();
        }

        Integer companyId = orderWork.getCompanyId();
        Integer manageCompanyId = orderWork.getManageCompanyId();
        if (OrderLogConsts.ORDER_LOG_TYPE_ASSIGN == logType && omsOperator instanceof OrderAssignDTO) {
            OrderAssignDTO orderAssignDTO = (OrderAssignDTO) omsOperator;
            companyId = orderAssignDTO.getCompanyId();
            manageCompanyId = orderAssignDTO.getManageCompanyId();
        }

        logger.info("[{}]新单同步到呼叫-发送队列", orderWork.getOrderId());
        CallSyncOrderDTO callSyncOrder = new CallSyncOrderDTO();
        callSyncOrder.setOrderId(orderWork.getOrderId());
        callSyncOrder.setPlat(orderWork.getPlat());
        callSyncOrder.setOrgOneId(orderWork.getOrgOneId());
        callSyncOrder.setOrgTwoId(orderWork.getOrgTwoId());
        callSyncOrder.setOrgThreeId(orderWork.getOrgThreeId());
        callSyncOrder.setOrgFourId(orderWork.getOrgFourId());
        callSyncOrder.setChannelId(orderWork.getChannelId());
        callSyncOrder.setCompanyId(companyId);
        callSyncOrder.setManageCompanyId(manageCompanyId);
        callSyncOrder.setPlatMark(platWork);
        callSyncOrder.setTelephone(StringUtils.defaultIfBlank(orderDetail.getTelephone(), ""));
        callSyncOrder.setTelephone2(StringUtils.defaultIfBlank(orderDetail.getTelephone2(), ""));
        callSyncOrder.setTelephone3(StringUtils.defaultIfBlank(orderDetail.getTelephone3(), ""));
        callSyncOrder.setCityId(orderWork.getCityId());
        callSyncOrder.setBizType(orderWork.getBizType());
        callSyncOrder.setCreateTime(DateUtil.toString(orderWork.getCreateTime() != null ? orderWork.getCreateTime() : DateUtil.getNow()));

        String json = JSON.toJSONString(callSyncOrder);
        String key = String.valueOf(orderWork.getWorkId());
        zmnMQSender.send(MqTopicConsts.ZMN_TOPIC_OMS, OmsMqTagConsts.ZMN_TOPIC_OMS_ORDER_WORK_SYNC_NEW_CALL, key, json);
    }

    /**
     * 同步订单给上传中心
     *
     * @param orderLog
     * @param orderWork
     */
    private void syncUplaodIasc(OrderLog orderLog, OrderWork orderWork) {

        if (Objects.isNull(orderLog) || Objects.isNull(orderWork)) {
            return;
        }

        // 上门节点上传
        if (!Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_VISIT) &&
                !Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_PAY)) {
            return;
        }

        orderChangeService.changeStatusSyncToUploadIASC(orderWork.getOrderId(), orderLog.getType());
    }

    /**
     * 获取日志内容
     *
     * @param dbOrderWork
     * @param omsOperator
     * @param orderLog
     * @param logType
     * @return
     */
    String getLogContent(OrderWork dbOrderWork, OmsOperator omsOperator, OrderLog orderLog, Integer logType) {
        String logContent = this.getLogContentSwitch(dbOrderWork, omsOperator, orderLog, logType);

        // 下面是通用附加信息
        StringBuilder sb = null;

        if (omsOperator.getAppPlat() != null) {
            sb = new StringBuilder();
            sb.append("app系统：");

            switch (omsOperator.getAppPlat()) {
                case AppConsts.APP_OS_ANDROID: {
                    sb.append("Android");
                    break;
                }
                case AppConsts.APP_OS_IOS: {
                    sb.append("IOS");
                    break;
                }
                default: {
                    sb.append(omsOperator.getAppPlat());
                    break;
                }
            }

            sb.append("\n版本号：V ");
            sb.append(omsOperator.getDisplayVersion());
        }

        if (sb != null) {
            if (StringUtils.isBlank(logContent)) {
                logContent = sb.toString();
            } else {
                logContent = logContent + "\n" + sb.toString();
            }
        }

        return logContent;
    }

    String getLogContentSwitch(OrderWork dbOrderWork, OmsOperator omsOperator, OrderLog orderLog, Integer logType) {
        String content = null;

        switch (logType) {
            case OrderLogConsts.ORDER_LOG_TYPE_UPDATE:
                // 修改工单日志
                content = updateOrder(dbOrderWork, omsOperator, orderLog);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_UPDATE_CHANNEL:
                // 组装修改渠道日志
                content = updateChannel(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_CHECKOUT:
                // 组装收单日志
                content = checkout(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_ACCOUNT:
                // 组装算账日志
                content = account(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MASTER_RETENTION:
                // 组装工程师提成日志
                content = masterRetention(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_ACCOUNT_RETENTION:
                // 组装SAAS算账提留日志
                content = masterRetention(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_CANCEL:
                // 组装取消日志
                content = cancel(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_REPLYVISIT:
                // 组装回访日志
                content = replyVisit(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_PART:
                // 组装核配件日志
                content = part(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_PART_ADD_REIMBURSE:
                // 组装外报配件和运杂费日志
                content = partAddReimburse(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_REMARK:
                // 组装内部日志
                content = remark(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_PLAT_MASTER_REMARK:
                // 组装运营平台工程师日志
                content = platMasterRemark(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_FACTORY_REMARK:
                // 组装商家日志
                content = factoryRemark(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_SERVICE_PROVIDER_REMARK:
                // 组装服务商日志
                content = serviceProviderRemark(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_TRACK:
                // 组装跟单日志
                content = track(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_DISCOUNT_ARTIFICIAL_OPERATOR:
                // 组装人工优惠（后台）日志
                content = discountArtificial(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_DISCOUNT_ARTIFICIAL_SP:
                // 组装人工优惠（服务商）日志
                content = discountArtificial(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_USE_COUPON:
                // 组装团购券日志
                content = discountGroupCoupon(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_DISCOUNT_ARTIFICIAL_MASTER:
                // 组装人工优惠（工程师）日志
                content = discountArtificial(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_WARRANTY:
                // 组装电子保单
                content = warranty(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_UPDATE_WARRANTY:
                // 组装修改电子保单
                content = updateWarranty(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_INVOICE:
                // 开发票日志
                content = invoice(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_INVOICE_REMIND:
                // 推送开票日志
                content = invoiceRemind(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MEM_MASTER_REVIEW:
                // 工程师审核
                content = memMasterReview(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MEM_PLAT_REVIEW:
                // 平台审核
                content = memPlatReview(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_PART_REIMBURSE:
                // 配件报销
                content = partReimburse(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_UPDATE_CHANNEL_PREPAY_AMOUNT:
                // 渠道预付
                content = updateChannelPrepayAmount(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_CHANNEL_PAY:
                // 渠道支付
                content = updateChannelPrepayAmount(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_UPDATE_CHANNEL_AMOUNT:
                // 改渠道费
                content = updateChannelAmount(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_SERVICEITEM:
                // 服务项
                content = serviceItem(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_QUOTATION:
                // 计价器报价
                content = quotation(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_CONFIRM:
                // 确认
                content = confirm(dbOrderWork, omsOperator, orderLog);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE:
                // 派单
                content = distribute(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_TAKE:
                // 领单
                content = takeOrder(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MASTER_LEAVE:
                // 出发
                content = leave(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_VISIT:
                // 上门
                content = visit(dbOrderWork, omsOperator);
                break;
            // 工程师申请多次上门
            case OrderLogConsts.ORDER_LOG_TYPE_APPLY_MULTIPLE_VISIT:
                content = applyMultipleVisit(dbOrderWork, omsOperator);
                break;
            // 工程师再次出发
            case OrderLogConsts.ORDER_LOG_TYPE_AGAIN_SET_OUT:
                content = againSetOut(dbOrderWork, omsOperator);
                break;
            // 工程师再次上门
            case OrderLogConsts.ORDER_LOG_TYPE_AGAIN_VISIT:
                content = againVisit(dbOrderWork, omsOperator);
                break;
            // 取消再次上门
            case OrderLogConsts.ORDER_LOG_TYPE_CANCEL_AGAIN_VISIT:
                content = cancelAgainVisit(dbOrderWork, omsOperator);
                break;
            // 工程师取消再次上门
            case OrderLogConsts.ORDER_LOG_TYPE_ENGINEER_CANCEL_AGAIN_VISIT:
                content = "取消缘由：用户取消服务";
                break;
            // 取消收款
            case OrderLogConsts.ORDER_LOG_TYPE_CANCEL_PAY:
                content = cancelOrderPay(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_VISIT_QR:
            case OrderLogConsts.ORDER_LOG_TYPE_USER_ATTENTION_QR:
                // 上门扫码
                content = visitQr(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MASTER_CHANGE_PRICE:
                // 工程师改价格
                content = masterChangePrice(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_PLAT_UPDATE_PRICE:
                // 平台改价格
                content = platChangePrice(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MANUALCODE:
                // 填保单号
                content = manualCode(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MASTER_REMARK:
                // 工程师备注
                content = masterRemark(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MASTER_INVOICE:
                // 工程师发票
                content = masterInvoiceInfo(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MASTER_INVOICE_PIC:
                // 工程师发票照片
                content = masterInvoicePic(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_ORDER_IMAGE:
                // 工单照片
                content = orderImage(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_ATTACHMENT_IMAGE:
                // 附件照片
                content = orderAttachmentImage(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_APPLIQUE_IMAGE:
                // 贴花照片
                content = appliqueImage(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MASTER_IMAGE:
                // 工单工程师照片
                content = masterImage(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_ORDER_PHOTO_AUTO:
                // 自动审核工单照片
                content = photoDetection(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_PAY:
                // 支付日志
                content = payLog(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_EXCEPTION_ORDER_PAY:
                // 异常支付日志（和正常支付日志共用方法）
                content = payLog(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_SERVICE_COMPLETE:
                // 服务完成日志
                content = serviceComplete(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_SERVICE_COMPLETE_REVIEW:
                // 完成审核日志
                content = serviceCompleteReview(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_COMPLETE:
                // 完成日志
                content = complete(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_CONTACT_USER:
                // 工程师联系用户
                content = contactUser(omsOperator, orderLog);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_COMMENT:
                // 评价
                content = comment(omsOperator, orderLog);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_COMMENT_REMARK:
                // 评价备注
                content = commentRemark(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_ASSIGN:
                // 分单
                content = assign(omsOperator, dbOrderWork);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_ASSIGN_BACK:
                // 分单撤回
                content = assignBack(omsOperator, dbOrderWork);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_ASSIGN_CONFIRM:
                // 接单
                content = assignConfirm(dbOrderWork);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE_BACK:
                // 派单撤回
                content = distributeBackConfirm(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_TURN:
                // 转单
                content = turn(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_CHANGE_STATUS:
                // 转单导致状态变更
                content = changeTurnStatus(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_OLD_PART_TO_FACTORY:
                // 旧件返厂
                content = oldPartToFactory(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_PART_REVIEW:
                // 配件审核
                content = partReview(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_OLD_PART_POST:
                // 邮寄旧件
                content = oldPartPost(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_PART_APPLY:
                // 申请厂商配件
                content = applyFcPart(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_ORDER_PHOTO:
                // 后台修改工单照片
                content = editOrderImage(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MASTER_MODIFY_DUTY_TIME:
                // 工程师改预约时间
                content = masterModifyDutyTime(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_APPLY_REFUND:
                // 退款
                content = applyRefund(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_REFUND_RESULT:
                // 退款结果
                content = refundResult(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MODIFY_PRODUCT:
                // 退款结果
                content = modifyProduct(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_REFUND:
                // 退款
                content = refund(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_REFUND_UPDATE:
                // 退款修改
                content = refundUpdate(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MODIFY_DUTY_TIME:
                // 修改预约时间
                content = masterModifyDutyTime(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_SIGN_IN:
                // 签到
                content = signIn(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_VERIFICATION:
                // 核销
                content = verification(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_UPDATE_ADDRESS:
                // 修改地址工单日志
                content = updateOrderAddress(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_ENTERPRISE_WX_LOG:
                // 企业微信添加成员日志记录
                content = enterpriseWeChatLog(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MODIFY_DIFFICULT_RATIO_ID:
                // 修改难度系数
                content = modifyDifficultRatio(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_CALL_LOG:
            case OrderLogConsts.ORDER_LOG_TYPE_IM_CALL_LOG:
            case OrderLogConsts.ORDER_LOG_TYPE_XNO_CALL_LOG:
                // 通话记录
                content = callRecordLog(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_NONSTANDARD:
                // 非标信息
                content = orderNonstandardLog(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_ORDER_SUSPEND:
                // 挂起
                content = orderWorkSuspend(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_EXPRESS_POST:
                // 快递信息日志记录
                content = updateOrderPostLog(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_NEW_MACHINE_PART:
                // 新机配件信息日志记录
                content = updateOrderNewMachinePartLog(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_NOT_CLAIM_ORDER:
                // 用户不认领订单
                content = nonClaimOrdertLog(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_REFUND_VOUCHER:
                content = refundVoucherLog(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_CHANGE_ASSIGNMENT:
                // 更改分配
                content = changeAssignmentOrdertLog(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_MASTER_SHARE:
                content = masterShare(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_REMINDER:
                content = reminder(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_ONE_CLICK_REMINDER:
                content = oneClickReminder(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_INPUT_COMPLETE_CODE:
                content = addCompleteCodeLog(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_PART_RETAIN:
                content = partRetain(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_XNO_UNBIND:
                content = unBindLog(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_XNO_BIND:
                content = bindLog(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_TEMP_XNO_BIND:
                content = tempBindLog(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_TEMP_XNO_UNBIND:
                content = tempUnBindLog(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_ORDER_WORK_TAG:
                content = orderWorkTagLog(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_REFUND_REVIEW:
                content = refundReview(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_COMPENSATE:
                content = compensate(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_COMPENSATE_UPDATE:
                content = updateCompensate(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_COMPENSATE_REVIEW:
                content = compensateReview(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_REMIT_VOUCHER:
                content = remitVoucher(dbOrderWork, omsOperator);
                break;
            // 验收
            case OrderLogConsts.ORDER_LOG_TYPE_ACCEPTANCE:
                content = acceptance(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_ENGINEER_REVIEW_CANCEL:
                content = cancelReviewLog(omsOperator);
                break;
            // 发起验收
            case OrderLogConsts.ORDER_LOG_TYPE_ADD_ACCEPTANCE:
                content = addAcceptance(omsOperator);
                break;
            // 工程师代验收
            case OrderLogConsts.ORDER_LOG_TYPE_ENGINEER_ACCEPTANCE:
                content = "工程师代验收";
                break;
            // 发起定金确认
            case OrderLogConsts.ORDER_LOG_TYPE_ADD_DEPOSIT_ACCEPTANCE:
                content = "工程师发起定金";
                break;
            // 定金确认
            case OrderLogConsts.ORDER_LOG_TYPE_DEPOSIT_ACCEPTANCE:
                content = "定金确认";
                break;
            // 工程师代确认
            case OrderLogConsts.ORDER_LOG_TYPE_ENGINEER_DEPOSIT_ACCEPTANCE:
                content = "工程师代确认";
                break;
            // 取消定金确认
            case OrderLogConsts.ORDER_LOG_TYPE_CANCEL_DEPOSIT_ACCEPTANCE:
                content = "取消定金确认";
                break;
            // 取消验收
            case OrderLogConsts.ORDER_LOG_TYPE_CANCEL_ACCEPTANCE:
                content = "取消验收";
                break;
            // 重复支付退款审核结果
            case OrderLogConsts.ORDER_LOG_TYPE_DUPLICATE_PAY_REFUND_AUDIT_RESULT:
                content = duplicatePayRefundApprove(omsOperator);
                break;
            // 重复支付退款结果
            case OrderLogConsts.ORDER_LOG_TYPE_DUPLICATE_PAY_REFUND_RESULT:
                content = duplicatePayRefundResult(dbOrderWork, omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_USER_CONFIRM_FAULT_PHEN:
                content = userConfirmFaultPhen(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_START_CHECK:
                content = startCheck(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_SUBMIT_CHECK_REPORT:
                content = submitCheckReport(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_PROCESS_CHECK_REPORT:
                content = processCheckReport(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_AGREE_REPAIR_RESULT_WITH_CAPTCHA:
                content = agreeRepairResultWithCaptcha(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_AGREE_REPAIR_RESULT:
                content = agreeRepairResult(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_USE_ENGINEER_DISCOUNT:
                content = useEngineerDiscount(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_USE_TIMES_CARD:
                content = useTimesCard(omsOperator);
                break;
            case OrderLogConsts.ORDER_LOG_TYPE_REFUND_DIFFERENCE:
                content = refundDifference(omsOperator);
                break;
            default:
                break;
        }

        return content;
    }

    private String remitVoucher(OrderWork dbOrderWork, OmsOperator omsOperator) {
        RemitVoucherDTO remitVoucherDTO = (RemitVoucherDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        log.append("凭证号：");
        for (VoucherDataDTO voucherDataDTO : remitVoucherDTO.getRefundVoucherData()) {
            log.append(voucherDataDTO.getRefundNo()).append("，已上传退款凭证照；");
        }
        log.append("\n");
        log.append("打款人：").append(remitVoucherDTO.getOperator()).append("\n");
        log.append("打款时间：").append(DateUtil.getNowFormatted()).append("\n");
        log.append("打款银行：").append(remitVoucherDTO.getPayerThirdAccountBank()).append("\n");
        log.append("打款银行账户：").append(remitVoucherDTO.getPayerThirdAccount());
        return log.toString();
    }

    /**
     * 验收
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    private String acceptance(OrderWork dbOrderWork, OmsOperator omsOperator) {
        OrderWorkAcceptanceDTO dto = (OrderWorkAcceptanceDTO) omsOperator;

        if (Objects.isNull(dto.getAcceptanceResultStatus())) {
            return null;
        }

        StringBuilder log = new StringBuilder();

        OrderWorkAcceptance acceptance = dto.getDbOrderWorkAcceptance();
        if (Objects.equals(acceptance.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_PAYMENT_CONFIRM)
                || Objects.equals(acceptance.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_PROGRESS_CONFIRM)) {
            log.append("收款确认");
        } else {
            log.append("服务验收");
        }

        log.append("\n状态：");
        switch (dto.getAcceptanceResultStatus()) {

            case OrderConsts.ORDER_ACCEPTANCE_STATUS_SUCCESS:
                if (Objects.equals(dto.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_DEPOSIT)) {
                    log.append("定金确认");
                } else {
                    log.append("通过");
                }
                break;
            case OrderConsts.ORDER_ACCEPTANCE_STATUS_FAIL:
                log.append("未通过");
                if (Objects.nonNull(dto.getReasonMap())) {
                    log.append("\n原因：");
                    dto.getReasonMap().values().forEach(str -> {
                        log.append(str).append(";");
                    });
                }
                if (NumberUtil.isNotNullOrZero(dto.getFailType())) {
                    log.append("\n验收失败类型：");
                    switch (dto.getFailType()) {
                        case OrderConsts.ORDER_ACCEPTANCE_FAIL_TYPE_INSPECTION_REPORT:
                            log.append("验机报告");
                            break;
                        case OrderConsts.ORDER_ACCEPTANCE_FAIL_TYPE_COST_DETAIL:
                            log.append("费用明细");
                            break;
                        case OrderConsts.ORDER_ACCEPTANCE_FAIL_TYPE_SERVICE_CONTENT:
                            log.append("服务内容");
                            break;
                        default:
                            break;
                    }
                }
                break;
            case OrderConsts.ORDER_ACCEPTANCE_STATUS_NON:
                log.append("工程师代验收");
                break;
            case OrderConsts.ORDER_ACCEPTANCE_STATUS_CANCEL:
                log.append("取消验收");
                break;
            default:
                return "";
        }
        return log.toString();
    }

    /**
     * 重复支付退款
     *
     * @param omsOperator
     * @return
     */
    private String duplicatePayRefundApprove(OmsOperator omsOperator) {
        DuplicatePayRefundDTO dto = (DuplicatePayRefundDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        log.append(omsOperator.getOperator()).append("同意退款\n");
        log.append("退款金额：").append(MoneyUtil.parseToYuanEndWithUnit(dto.getOrderPay().getAmount()));
        log.append("\n退款方式：原路退款\n退款缘由：重复支付");
        return log.toString();
    }


    /**
     * 重复支付退款审批
     *
     * @param omsOperator
     * @return
     */
    private String duplicatePayRefundResult(OrderWork dbOrderWork, OmsOperator omsOperator) {
        com.zmn.oms.model.dto.order.pay.RefundResultDTO dto = (com.zmn.oms.model.dto.order.pay.RefundResultDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        log.append("退款金额：")
                .append(MoneyUtil.parseToYuanEndWithUnit(dto.getRefundAmount()))
                .append("，退款结果：已退款");
        if (NumberUtil.isNullOrZero(dbOrderWork.getChannelPrepayAmount())) {
            log.append("，退款渠道：");
            log.append(PayConsts.getPayChannelName(dto.getChannelId()));
        }
        log.append("，退款流水号：").append(dto.getRefundOutTradeNo());
        return log.toString();
    }

    private String compensateReview(OrderWork dbOrderWork, OmsOperator omsOperator) {
        CompensateReviewDTO compensateReviewDTO = (CompensateReviewDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        if (Objects.equals(compensateReviewDTO.getReviewStatus(), GlobalConsts.YES)) {
            log.append("审核通过");
        } else if (Objects.equals(compensateReviewDTO.getReviewStatus(), GlobalConsts.NO)) {
            log.append("审核不通过");
        }
        log.append("\n");
        log.append("备注：").append(compensateReviewDTO.getContent());
        return log.toString();
    }

    private String updateCompensate(OrderWork dbOrderWork, OmsOperator omsOperator) {
        CompensateDTO compensateWorkDTO = (CompensateDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        log.append("修改后的信息：").append("\n");
        String reason = compensateWorkDTO.getReasonList()
                .stream()
                .map(KVDict::getText)
                .collect(Collectors.joining(","));
        log.append("损坏原因：").append(reason).append("\n");
        log.append("损坏物品：").append(compensateWorkDTO.getDamageGood()).append("\n");
        log.append("赔偿金额：").append(MoneyUtil.parseToYuan(compensateWorkDTO.getCompensateAmount())).append("\n");
        log.append("赔偿方式：");
        switch (compensateWorkDTO.getPayTargetChannelId()) {
            case PayConsts.PAY_CHANNEL_PLATFORM_ALIPAY:
                log.append("支付宝：").append(compensateWorkDTO.getPayeeThirdAccountName()).append("/").append(compensateWorkDTO.getPayeeThirdAccount());
                break;
            case PayConsts.PAY_CHANNEL_PLATFORM_WEIXINPAY:
                log.append("微信：").append(compensateWorkDTO.getPayeeThirdAccountName()).append("/").append(compensateWorkDTO.getPayeeThirdAccount());
                break;
            case PayConsts.PAY_CHANNEL_PLATFORM_BANKTRANSFER:
                log.append("银行卡：").append(compensateWorkDTO.getPayeeThirdAccountName()).append("/").append(compensateWorkDTO.getPayeeThirdAccount()).append("/").append(compensateWorkDTO.getPayeeThirdAccountBank());
                break;
            case PayConsts.PAY_CHANNEL_PLATFORM_CASH:
                log.append("现金");
                break;
        }
        log.append("\n");
        log.append("备注：").append(compensateWorkDTO.getContent());
        return log.toString();
    }

    private String compensate(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ZsNormalCompensateWorkDTO compensateWorkDTO = (ZsNormalCompensateWorkDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        String reason = compensateWorkDTO.getReasonList()
                .stream()
                .map(KVDict::getText)
                .collect(Collectors.joining(","));
        log.append("损坏原因：").append(reason).append("\n");
        log.append("损坏物品：").append(compensateWorkDTO.getDamageGood()).append("\n");
        log.append("赔偿金额：").append(MoneyUtil.parseToYuan(compensateWorkDTO.getCompensateAmount())).append("\n");
        log.append("赔偿方式：");
        switch (compensateWorkDTO.getPayTargetChannelId()) {
            case PayConsts.PAY_CHANNEL_PLATFORM_ALIPAY:
                log.append("支付宝：").append(compensateWorkDTO.getPayeeThirdAccountName()).append("/").append(compensateWorkDTO.getPayeeThirdAccount());
                break;
            case PayConsts.PAY_CHANNEL_PLATFORM_WEIXINPAY:
                log.append("微信：").append(compensateWorkDTO.getPayeeThirdAccountName()).append("/").append(compensateWorkDTO.getPayeeThirdAccount());
                break;
            case PayConsts.PAY_CHANNEL_PLATFORM_BANKTRANSFER:
                log.append("银行卡：").append(compensateWorkDTO.getPayeeThirdAccountName()).append("/").append(compensateWorkDTO.getPayeeThirdAccount()).append("/").append(compensateWorkDTO.getPayeeThirdAccountBank());
                break;
            case PayConsts.PAY_CHANNEL_PLATFORM_CASH:
                log.append("现金");
                break;
        }
        log.append("\n");
        log.append("备注：").append(compensateWorkDTO.getContent());
        return log.toString();
    }

    private String refundReview(OrderWork dbOrderWork, OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();
        RefundReviewBO refundReviewBO = (RefundReviewBO) omsOperator;
        RefundDTO refundDTO = JSON.parseObject(refundReviewBO.getReviewData(), RefundDTO.class);
        log.append(refundReviewBO.getReviewer());
        if (Objects.equals(refundReviewBO.getReviewStatus(), OrderConsts.OMS_ORDER_REVIEW_STATUS_CHECK_SUCCESS)) {
            log.append("同意退款，退款金额：");
        } else if (Objects.equals(refundReviewBO.getReviewStatus(), OrderConsts.OMS_ORDER_REVIEW_STATUS_CHECK_FAIL)) {
            log.append("拒绝退款，退款金额：");
        }
        log.append(MoneyUtil.parseToYuanStartWithUnit(refundDTO.getRefundAmount()));
        return log.toString();
    }

    private String refundVoucherLog(OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();
        RefundVoucherDTO dto = (RefundVoucherDTO) omsOperator;
        String voucherNo = dto.getRefundVoucherData()
                .stream()
                .map(VoucherDataDTO::getRefundNo)
                .collect(Collectors.joining(","));
        log.append("退款凭证号：").append(voucherNo).append("，已上传退款凭证照；");
        log.append("\n");
        log.append("打款人：").append(omsOperator.getOperator());
        log.append("\n");
        log.append("打款时间：").append(DateUtil.getNowFormatted());
        log.append("\n");
        log.append("打款银行：").append(dto.getPayerThirdAccountBank());
        log.append("\n");
        log.append("打款银行账户：").append(dto.getPayerThirdAccount());
        log.append("\n");
        log.append("退款手续费：").append(MoneyUtil.parseToYuan(dto.getRefundPoundage()));
        if (StringUtil.isNotBlank(dto.getRefundVoucherRemark())) {
            log.append("\n");
            log.append("备注：").append(dto.getRefundVoucherRemark());
        }

        return log.toString();
    }

    private String addCompleteCodeLog(OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();
        CompleteCodeDTO dto = (CompleteCodeDTO) omsOperator;
        log.append("核销码：").append(dto.getCompleteCode());
        return log.toString();
    }


    private String partRetain(OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();
        MasterPartRetainDTO dto = (MasterPartRetainDTO) omsOperator;
        if (Objects.equals(dto.getRetainPart(), GlobalConsts.YES)) {
            log.append("稍后报销");
        } else {
            log.append("取消稍后报销");
        }
        return log.toString();
    }


    /**
     * 上门扫码
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    private String visitQr(OrderWork dbOrderWork, OmsOperator omsOperator) {
        MasterVisitQrDTO masterVisitQrDTO = (MasterVisitQrDTO) omsOperator;
        if (StringUtil.isNotBlank(masterVisitQrDTO.getOpenId())) {
            StringBuilder log = new StringBuilder();
            log.append("用户已扫码");
            if (StringUtils.isNotBlank(masterVisitQrDTO.getNickname())) {
                log.append("\n");
                log.append("用户微信昵称：").append(masterVisitQrDTO.getNickname());
            }
            if (StringUtils.isNotBlank(masterVisitQrDTO.getOpenId())) {
                log.append("\n");
                log.append("用户微信OpenId：").append(masterVisitQrDTO.getOpenId());
            }
            if (StringUtils.isNotBlank(masterVisitQrDTO.getUnionId())) {
                log.append("\n");
                log.append("用户微信UnionId：").append(masterVisitQrDTO.getUnionId());
            }
            if (StringUtils.isNotBlank(masterVisitQrDTO.getAppName())) {
                log.append("\n");
                log.append("关注公众号：").append(masterVisitQrDTO.getAppName());
            }
            return log.toString();
        } else {
            return "用户未扫码";
        }
    }

    /**
     * 申请厂商配件
     *
     * @param omsOperator
     * @return
     */
    private String applyFcPart(OmsOperator omsOperator) {
        OrderFactoryPartDTO orderFactoryPartDTO = (OrderFactoryPartDTO) omsOperator;

        StringBuilder sb = new StringBuilder();
        if (org.apache.commons.lang3.StringUtils.isNotBlank(orderFactoryPartDTO.getOperatorRemark())) {
            sb.append(orderFactoryPartDTO.getOperatorRemark());
        }
        if (org.apache.commons.lang3.StringUtils.isNotBlank(orderFactoryPartDTO.getOperatorLogRemark())) {
            sb.append(orderFactoryPartDTO.getOperatorLogRemark());
        }

        return sb.toString();
    }

    /**
     * 派单撤回
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    private String distributeBackConfirm(OrderWork dbOrderWork, OmsOperator omsOperator) {

        StringBuilder log = new StringBuilder();
        String masterName = dbOrderWork.getMasterName();
        if (StringUtil.isNotBlank(masterName)) {
            log.append("工单从工程师：").append(masterName);
        }
        log.append("撤回至平台;\n");
        if (StringUtils.isNotBlank(omsOperator.getOperatorRemark())) {
            log.append("备注：").append(omsOperator.getOperatorRemark());
        }

        return log.toString();
    }

    /**
     * 转单
     *
     * @param dbOrderWork
     * @return
     */
    private String turn(OrderWork dbOrderWork, OmsOperator omsOperator) {
        OrderTurnDTO orderTurnDTO = (OrderTurnDTO) omsOperator;

        StringBuilder log = new StringBuilder();

        if (Objects.equals(orderTurnDTO.getOperatorType(), GlobalConsts.OPERATE_USER_TYPE_SYSTEM)) {
            log.append("自动转单至平台：" + GlobalConsts.getPlatName(orderTurnDTO.getPlatWork()));
        } else {
            //拼接备注
            log.append(String.format("工单由 %s 转至 %s", GlobalConsts.getPlatName(dbOrderWork.getPlatWork()),
                    GlobalConsts.getPlatName(orderTurnDTO.getPlatWork())));
            if (StringUtil.isNotBlank(orderTurnDTO.getOperatorRemark())) {
                log.append(",备注:").append(orderTurnDTO.getOperatorRemark());
            }
        }
        return log.toString();
    }

    /**
     * 转单导致状态变更
     *
     * @param dbOrderWork
     * @return
     */
    private String changeTurnStatus(OrderWork dbOrderWork, OmsOperator omsOperator) {

        StringBuilder log = new StringBuilder();

        return log.toString();
    }

    /**
     * 旧件返厂
     *
     * @param omsOperator
     * @return
     */
    private String oldPartToFactory(OmsOperator omsOperator) {
        FcOrderOldPartReturn part = (FcOrderOldPartReturn) omsOperator;

        StringBuilder log = new StringBuilder();

        //拼接备注
        if (!Objects.isNull(part.getAddress())) {
            String[] paramsStr = part.getAddress().split("-");
            log.append(
                    String.format("返厂地址：%s，姓名:%s，电话:%s", paramsStr[0], paramsStr[1], MobileUtil.formatHideTel(paramsStr[2])));
            if (!Objects.isNull(part.getExpressCompany())) {
                log.append(String.format("，指定快递公司：%s", part.getExpressCompany()));
            }
        } else {
            log.append("返厂地址:配件不需要返厂");
        }
        return log.toString();
    }

    /**
     * 邮寄旧件
     *
     * @param omsOperator
     * @return
     */
    private String oldPartPost(OmsOperator omsOperator) {
        // 服务商邮寄旧件给厂商
        if (omsOperator instanceof OrderPartPostListDTO) {
            OrderPartPostListDTO oldPartPost = (OrderPartPostListDTO) omsOperator;

            StringBuilder log = new StringBuilder();
            log.append("邮寄旧件：");
            for (OrderPartPostDTO orderPartPost : oldPartPost.getPartPostList()) {
                log.append("快递公司：").append(orderPartPost.getExpressCompany()).append("快递单号：")
                        .append(orderPartPost.getExpressCode()).append(";");
            }
            return log.toString();
        }
        // 工程师邮寄旧件给厂商
        else if (omsOperator instanceof FactoryPartPostDTO) {
            FactoryPartPostDTO factoryPartPostDTO = (FactoryPartPostDTO) omsOperator;

            String logStr = String.format("邮寄至厂家，已发送，快递公司：%s，快递单号：%s", factoryPartPostDTO.getExpressCompany(),
                    factoryPartPostDTO.getExpressCode());
            if (org.apache.commons.lang3.StringUtils.isNotBlank(factoryPartPostDTO.getRemark())) {
                logStr = String.format("%s，备注：%s", logStr, factoryPartPostDTO.getRemark());
            }
            return logStr;
        }

        return null;
    }

    /**
     * 配件审核
     *
     * @param omsOperator
     * @return
     */
    private String partReview(OmsOperator omsOperator) {
        FcOrderPartReview partReview = (FcOrderPartReview) omsOperator;

        StringBuilder log = new StringBuilder("厂商配件：");
        for (OrderFactoryPart part : partReview.getParts()) {
            // 拼接备注
            log.append(String.format("配件名称：%s ,数量 %s%s，", part.getPartName(), part.getNumber(), part.getUnit()));
            if (StringUtil.isNotBlank(part.getPicSrc1())) {
                log.append(String.format("，工程师拍照:[{{img:%s}}]", part.getPicSrc1()));
            }
            if (StringUtil.isNotBlank(part.getPicSrc2())) {
                log.append(String.format("，[{{img:%s}}]", part.getPicSrc2()));
            }
            if (StringUtil.isNotBlank(part.getPicSrc3())) {
                log.append(String.format("，[{{img:%s}}]", part.getPicSrc3()));
            }
            log.append("审核结果：");
            if (Objects.equals(part.getReviewStatus(), 2)) {
                log.append("成功；");
            } else if (Objects.equals(part.getReviewStatus(), 3)) {
                log.append("失败；");
            }
        }

        return log.toString().substring(0, log.length() - 1);
    }

    /**
     * 服务商备注
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    private String serviceProviderRemark(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ZsRemarkDTO remarkDTO = (ZsRemarkDTO) omsOperator;
        StringBuilder log = new StringBuilder();

        if (StringUtil.isNotBlank(remarkDTO.getServiceProviderRemark())) {
            log.append(remarkDTO.getServiceProviderRemark());
        }

        return log.toString();
    }

    /**
     * 分单撤回
     *
     * @param omsOperator
     * @return
     */
    private String assignBack(OmsOperator omsOperator, OrderWork dbOrderWork) {

        StringBuilder log = new StringBuilder();
        log.append("从公司：").append(dbOrderWork.getCompanyName());

        String masterName = dbOrderWork.getMasterName();
        if (StringUtil.isNotBlank(masterName)) {
            log.append(",工程师：").append(masterName);
        }
        log.append("- 撤回至平台;\n");
        if (StringUtils.isNotBlank(omsOperator.getOperatorRemark())) {
            log.append("备注：").append(omsOperator.getOperatorRemark());
        }

        return log.toString();
    }

    /**
     * 分单
     *
     * @param dbOrderWork
     * @return
     */
    private String assignConfirm(OrderWork dbOrderWork) {
        return String.format("%s已接单", dbOrderWork.getCompanyName());
    }

    /**
     * 分单
     *
     * @param omsOperator
     * @param dbOrderWork
     * @return
     */
    private String assign(OmsOperator omsOperator, OrderWork dbOrderWork) {
        OrderAssignDTO orderAssignDTO = (OrderAssignDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        if (Objects.equals(orderAssignDTO.getProportion(), GlobalConsts.NO)) {
            log.append("[分单配比，直营:非直营=3:1]").append("\n");
        }
        if (Objects.equals(dbOrderWork.getPlatWork(), GlobalConsts.PLAT_MARK_ZMN)) {
            log.append("执行子公司：");
            log.append(orderAssignDTO.getCompanyName());
            log.append("，");
        }
        log.append("执行服务商：");
        log.append(orderAssignDTO.getManageCompanyName());
        if (StringUtil.isNotBlank(orderAssignDTO.getOperatorRemark())) {
            log.append("\n备注：").append(orderAssignDTO.getOperatorRemark());
        }
        return log.toString();
    }

    /**
     * 评价备注
     *
     * @param omsOperator
     * @return
     */
    private String commentRemark(OmsOperator omsOperator) {
        ZsCommentRemarkDTO commentRemarkDTO = (ZsCommentRemarkDTO) omsOperator;
        StringBuilder log = new StringBuilder();

        List<KVDict> codeMapList = commentRemarkDTO.getCodeMapList();
        if (CollectionUtils.isNotEmpty(codeMapList)) {
            for (KVDict kvDict : codeMapList) {
                log.append(kvDict.getText());
                log.append(",");
            }
        }
        return log.toString();
    }

    /**
     * 优惠券优惠
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    private String discountGroupCoupon(OrderWork dbOrderWork, OmsOperator omsOperator) {
        DiscountCouponDTO groupCouponDTO = (DiscountCouponDTO) omsOperator;
        // 优惠券使用失败只显示失败原因
        if (NumberUtil.isNullOrZero(groupCouponDTO.getType()) && NumberUtil.isNullOrZero(groupCouponDTO.getAmount())) {
            return groupCouponDTO.getRemark();
        }

        StringBuilder log = new StringBuilder();
        Integer thirdPlatEnum = groupCouponDTO.getThirdType() != null ? groupCouponDTO.getThirdType() : ThirdPlatEnum.THIRD_COUP_TYPE_OTHER.getKey();
        log.append(ThirdPlatEnum.getValue(thirdPlatEnum));// 优惠平台
        log.append("优惠券优惠：");
        log.append(groupCouponDTO.getItemCode());
        log.append("\n优惠类型：");
        log.append(OrderConsts.getDiscountTypeName(groupCouponDTO.getType()));
        log.append("\n优惠金额: ");
        String amountStr = this.amount2String(groupCouponDTO.getAmount());
        log.append(StringUtils.defaultString(amountStr));
        return log.toString();
    }

    /**
     * 评价
     *
     * @param omsOperator
     * @param orderLog
     * @return
     */
    String comment(OmsOperator omsOperator, OrderLog orderLog) {
        OrderCommentDTO orderCommentDTO = (OrderCommentDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        log.append("评价类型：");
        log.append(OrderConsts.getCommentTypeName(orderCommentDTO.getType()));
        log.append("\n评分: ");
        log.append(orderCommentDTO.getScore());
        List<MapDTO> codeMapList = orderCommentDTO.getCodeMapList();
        if (codeMapList != null && !codeMapList.isEmpty()) {
            log.append("\n选项：");
            codeMapList.forEach(e -> {
                String mapName = e.getMapName();
                log.append(mapName);
                log.append(",");
            });
        }
        String content = orderCommentDTO.getContent();
        if (StringUtil.isNotBlank(content)) {
            log.append("\n内容：");
            log.append(content);
        }
        return log.toString();
    }

    /**
     * 平台改价格
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String platChangePrice(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ZsUpdatePriceDTO updatePriceDTO = (ZsUpdatePriceDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        Integer originalAmount = updatePriceDTO.getOriginalAmount();
        if (originalAmount != null) {
            log.append("订单金额：");
            String originalAmountStr = this.amount2String(dbOrderWork.getOriginalAmount());
            log.append(StringUtils.defaultString(originalAmountStr));
            log.append(" -> ");
            log.append(this.amount2String(originalAmount));
        }

        if (!Objects.equals(updatePriceDTO.getOldAmount(), updatePriceDTO.getAmount())) {
            if (Objects.nonNull(updatePriceDTO.getAmount())) {
                if (Objects.equals(updatePriceDTO.getAmountType(), OrderPayConsts.ORDER_PAY_DEPOSIT)) {
                    log.append("\n定金");
                } else {
                    log.append("\n进度款");
                }
                log.append(StringUtils.defaultString(this.amount2String(updatePriceDTO.getOldAmount())));
                log.append(" -> ");
                log.append(this.amount2String(updatePriceDTO.getAmount()));
            }
        }

        Integer depositAmount = updatePriceDTO.getDepositAmount();
        if (depositAmount != null) {
            log.append("\n定金：");
            String depositAmountStr = this.amount2String(dbOrderWork.getDepositAmount());
            log.append(StringUtils.defaultString(depositAmountStr));
            log.append(" -> ");
            log.append(this.amount2String(depositAmount));
        }

        // 修改进度款金额
        /*if (Objects.nonNull(updatePriceDTO.getProgressAmount())) {
            log.append("\n进度款");
            log.append(StringUtils.defaultString(this.amount2String(updatePriceDTO.getOldProgressAmount())));
            log.append(" -> ");
            log.append(this.amount2String(depositAmount));
        }*/

        String beforeMasterName = null;
        boolean beforeOnlyVisit = Objects.equals(dbOrderWork.getOnlyVisit(), GlobalConsts.YES);
        beforeMasterName = beforeOnlyVisit ? "上门费" : "工程师收款金额";

        String afterMasterName = null;
        boolean afterOnlyVisit = Objects.equals(updatePriceDTO.getOnlyVisit(), GlobalConsts.YES);
        afterMasterName = afterOnlyVisit ? "上门费" : "工程师收款金额";

        Integer masterAmount = updatePriceDTO.getMasterAmount();
        if (masterAmount != null) {
            log.append("\n");
            log.append(beforeMasterName);
            String masterAmountStr = this.amount2String(dbOrderWork.getMasterAmount());
            log.append(StringUtils.defaultString(masterAmountStr));
            log.append(" -> ");
            log.append(afterMasterName);
            log.append(this.amount2String(masterAmount));
        }

        String operatorLogRemark = updatePriceDTO.getOperatorRemark();
        if (StringUtil.isNotBlank(operatorLogRemark)) {
            log.append("\n 改价缘由：");
            log.append(operatorLogRemark);
        }

        return log.toString();
    }

    /**
     * 平台审核
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String memPlatReview(OrderWork dbOrderWork, OmsOperator omsOperator) {
        OrderMemberPlatReviewDTO memberPlatReviewDTO = (OrderMemberPlatReviewDTO) omsOperator;
        StringBuilder log = new StringBuilder();

        Integer platReviewDeviceResult = memberPlatReviewDTO.getPlatReviewDeviceResult();
        String platReviewDeviceRemark = memberPlatReviewDTO.getPlatReviewDeviceRemark();
        log.append("整机审核结果：");
        log.append(OrderConsts.getMemberReviewResultStatusName(platReviewDeviceResult));
        if (StringUtil.isNotBlank(platReviewDeviceRemark)) {
            log.append("整机审核备注：");
            log.append(platReviewDeviceRemark);
        }

        Integer platReviewFragilePasteResult = memberPlatReviewDTO.getPlatReviewFragilePasteResult();
        String platReviewFragilePasteRemark = memberPlatReviewDTO.getPlatReviewFragilePasteRemark();
        log.append("\n易碎贴审核结果：");
        log.append(OrderConsts.getMemberReviewResultStatusName(platReviewFragilePasteResult));
        if (StringUtil.isNotBlank(platReviewFragilePasteRemark)) {
            log.append("易碎贴审核备注：");
            log.append(platReviewFragilePasteRemark);
        }

        Integer platReviewNameplateResult = memberPlatReviewDTO.getPlatReviewNameplateResult();
        String platReviewNameplateRemark = memberPlatReviewDTO.getPlatReviewNameplateRemark();
        log.append("\n铭牌审核结果：");
        log.append(OrderConsts.getMemberReviewResultStatusName(platReviewNameplateResult));
        if (StringUtil.isNotBlank(platReviewNameplateRemark)) {
            log.append("铭牌审核备注：");
            log.append(platReviewNameplateRemark);
        }

        return log.toString();
    }

    /**
     * 工程师审核
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String memMasterReview(OrderWork dbOrderWork, OmsOperator omsOperator) {
        OrderMemberMasterReviewDTO memberMasterReviewDTO = (OrderMemberMasterReviewDTO) omsOperator;
        StringBuilder log = new StringBuilder();

        log.append("整机照片：{{[img:");
        log.append(memberMasterReviewDTO.getMasterDeviceImageSrc());
        log.append("]}}");

        log.append("\n易碎贴照片：{{[img:");
        log.append(memberMasterReviewDTO.getMasterFragilePasteImageSrc());
        log.append("]}}");

        log.append("\n铭牌照片：{{[img:");
        log.append(memberMasterReviewDTO.getMasterNameplateImageSrc());
        log.append("]}}");

        log.append("\n审核结果：");
        log.append(OrderConsts.getMemberReviewResultStatusName(memberMasterReviewDTO.getMasterReviewResult()));
        return log.toString();
    }

    /**
     * 组装电子保单操作log
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String warranty(OrderWork dbOrderWork, OmsOperator omsOperator) {
        OrderWarrantyDTO warrantyDTO = (OrderWarrantyDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        log.append("填写保修范围:\n");
        log.append(warrantyDTO.getProductName());
        log.append(",");

        warrantyDTO.getFault().forEach(fault -> {
            log.append(fault.getMapName());
            log.append(",");
        });

        if (StringUtil.isNotBlank(warrantyDTO.getRemark())) {
            log.append(warrantyDTO.getRemark());
            log.append(",");
        }
        if (warrantyDTO.getMonth() != null) {
            log.append(warrantyDTO.getMonth());
            log.append("个月");
        } else {
            if (NumberUtil.isNotNullOrZero(warrantyDTO.getAddDay())) {
                log.append(warrantyDTO.getAddDay());
            } else {
                log.append(warrantyDTO.getDay());
            }
            log.append("天");

        }
        return log.toString();
    }

    /**
     * 修改电子保单操作log
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String updateWarranty(OrderWork dbOrderWork, OmsOperator omsOperator) {
        OrderWarrantyUpdateDTO warrantyDTO = (OrderWarrantyUpdateDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        log.append("修改保修范围：\n");
        if (NumberUtil.isNotNullOrZero(warrantyDTO.getReWorkId())) {
            log.append("返修单号：").append(warrantyDTO.getReWorkId()).append(" 已完成，已自动延保\n");
        }
        if (StringUtils.isNotBlank(warrantyDTO.getCode())) {
            log.append("保修卡号：").append(warrantyDTO.getCode() + "\n");
        }
        if (NumberUtil.isNotNullOrZero(warrantyDTO.getAddDay())) {
            log.append("延长保修：").append(warrantyDTO.getAddDay() + "天\n");
        }
        if (Objects.nonNull(warrantyDTO.getExpiredTime()) && Objects.nonNull(warrantyDTO.getOldExpiredTime())) {
            String expiredTimeLog = String.format("保修时间：%s -> %s", DateUtil.toString(warrantyDTO.getOldExpiredTime()), DateUtil.toString(warrantyDTO.getExpiredTime()));
            log.append(expiredTimeLog).append("\n");
        }
        return log.toString();
    }

    /**
     * 服务项目
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String serviceItem(OrderWork dbOrderWork, OmsOperator omsOperator) {
        AddOrderServiceItemDTO orderServiceItemDTO = (AddOrderServiceItemDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        List<OrderServiceItem> orderServiceItems = orderServiceItemDTO.getOrderServiceItemList();


        for (int i = 0; i < orderServiceItems.size(); i++) {
            OrderServiceItem orderServiceItem = orderServiceItems.get(i);

            if (i > 0) {
                log.append("\n");
            }

            log.append(Optional.ofNullable(orderServiceItem.getProductName()).orElse(""));
            log.append("产品服务项目：");
            log.append(orderServiceItem.getServItemName());
            log.append("服务项目（");
            log.append(orderServiceItem.getServItemGroupName());
            log.append("等级），数量：");
            log.append(orderServiceItem.getNumber());
            // 保内保外都记录价格 wangxiaokun 20200902
            log.append("，价格：");
            if (NumberUtil.isNotNullOrZero(orderServiceItem.getTieredTotalPrice())) {
                log.append(this.amount2String(orderServiceItem.getTieredTotalPrice()));
            } else {
                log.append(this.amount2String(orderServiceItem.getItemPrice() * orderServiceItem.getNumber()));
            }
        }

        return log.toString();
    }

    /**
     * 计价器报价
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String quotation(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ModifyQuotationDTO modifyQuotationDTO = (ModifyQuotationDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        if (Objects.equals(modifyQuotationDTO.getNegotiatedPriceFlag(), GlobalConsts.YES)) {
            log.append("议价清单：\n");
        }
        if (NumberUtil.isNotNullOrZero(modifyQuotationDTO.getUserId())) {
            log.append("用户ID：");
            log.append(modifyQuotationDTO.getUserId());
            log.append("\n");
        }
        // 品牌变更日志
        log.append(Optional.ofNullable(modifyQuotationDTO.getOperatorLogRemark()).orElse(""));

        List<OrderServiceItem> orderServiceItems = modifyQuotationDTO.getOrderServiceItems();
        orderServiceItems.forEach(orderServiceItem -> {
            log.append(orderServiceItem.getProductName());
            log.append("产品服务项目：");
            log.append(orderServiceItem.getServItemName());
            log.append("服务项目（");
            log.append(orderServiceItem.getServItemGroupName());
            log.append("等级），数量：");
            log.append(orderServiceItem.getNumber());
            // 保外记录价格，保内不记录
            if (Objects.equals(dbOrderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)) {
                log.append("，价格：");
                if (NumberUtil.isNotNullOrZero(orderServiceItem.getTieredTotalPrice())) {
                    log.append(this.amount2String(orderServiceItem.getTieredTotalPrice()));
                } else {
                    log.append(this.amount2String(orderServiceItem.getItemPrice() * orderServiceItem.getNumber()));
                }
            }
            log.append("\n");
        });

        if (NumberUtil.isNotNullOrZero(modifyQuotationDTO.getCityManageDiscountAmount())) {
            log.append("城市经理优惠金额：");
            log.append(this.amount2String(modifyQuotationDTO.getCityManageDiscountAmount()));
        }
        if (NumberUtil.isNotNullOrZero(modifyQuotationDTO.getDiscountAmount())) {
            log.append("\n人工优惠，优惠总金额：");
            log.append(this.amount2String(modifyQuotationDTO.getDiscountAmount()));
        }
        return log.toString();
    }

    /**
     * 更新渠道预付
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String updateChannelPrepayAmount(OrderWork dbOrderWork, OmsOperator omsOperator) {

        ZsUpdateChannelPrepayAmountDTO updateChannelPrepayAmountDTO = (ZsUpdateChannelPrepayAmountDTO) omsOperator;
        Integer remove = updateChannelPrepayAmountDTO.getRemove();
        StringBuilder log = new StringBuilder();
        if (Objects.equals(remove, GlobalConsts.YES)) {
            log.append("删除渠道预付");
        } else {
            if (StringUtils.isNotBlank(updateChannelPrepayAmountDTO.getChannelPrepayCertificateSrc())) {
                log.append(String.format("{{[img:%s]}}", updateChannelPrepayAmountDTO.getChannelPrepayCertificateSrc()));
            }
            log.append("渠道预付：");
            log.append(this.amount2StringNullAs0(dbOrderWork.getChannelPrepayAmount()));
            log.append("->");
            log.append(this.amount2StringNullAs0(updateChannelPrepayAmountDTO.getChannelPrepayAmount()));
        }
        if (CollectionUtil.isNotNullOrEmpty(updateChannelPrepayAmountDTO.getChannelPrepayAmountDetailList())) {
            log.append("\n");
            int sum = 0;
            for (KVDict dict : updateChannelPrepayAmountDTO.getChannelPrepayAmountDetailList()) {
                log.append(dict.getText() + "：");
                int amount = Integer.parseInt(dict.getValue().toString());
                log.append(MoneyUtil.parseToYuanStartWithUnit(amount) + "；");
                sum += amount;
            }
            log.append("实收金额：" + MoneyUtil.parseToYuanStartWithUnit(updateChannelPrepayAmountDTO.getChannelPrepayAmount() - sum));
        } else {
            log.append("实收金额：" + MoneyUtil.parseToYuanStartWithUnit(updateChannelPrepayAmountDTO.getChannelPrepayAmount()));
        }
        return log.toString();
    }

    /**
     * 配件报销日志
     *
     * @param dbOrderWork
     * @param omsOperator
     */
    String partReimburse(OrderWork dbOrderWork, OmsOperator omsOperator) {
        // 只将报销成功的配件计算到总申报金额中。
        StringBuilder log = new StringBuilder();

        // 总申报金额
        Integer declareAmount = 0;

        ZsPartReimburseGroupDTO partReimburseGroupDTO = (ZsPartReimburseGroupDTO) omsOperator;

        // 循环每组【报销配件】
        List<OrderPart> orderParts = orderPartBService.listPartReimburseByOrderId(dbOrderWork.getOrderId());

        logger.info("OrderWorkBaseLogAspect#partReimburse  orderParts：{}", orderParts);
        // 临时map，为OrderPart的price设置为前台传递过来的金额
        Map<Long, PartPricePostDTO> tempMap = partReimburseGroupDTO.getZsPartReimburseList().stream()
                .map(ZsPartReimburseDTO::getPartPricePostDTO)
                .flatMap(Collection::stream)
                .collect(Collectors.toMap(PartPricePostDTO::getOrderPartId, orderPart -> orderPart, (t, t2) -> t));

        // 用于判断当前报销单是否是系统报销的
        Map<String, ZsPartReimburseDTO> partReimburseMap = partReimburseGroupDTO.getZsPartReimburseList().stream()
                .collect(Collectors.toMap(ZsPartReimburseDTO::getApplyId, partReimburse -> partReimburse));

        for (OrderPart orderPart : orderParts) {

            // 根据页面提交的数据重新赋值
            ZsPartReimburseDTO partReimburseDTO = partReimburseMap.get(orderPart.getReimburseId());
            PartPricePostDTO partPricePostDTO = tempMap.get(orderPart.getOrderPartId());

            Integer totalAmount = 0;

            if (partPricePostDTO != null) {
                orderPart.setPrice(partPricePostDTO.getPrice());
                orderPart.setDeclarePrice(partPricePostDTO.getDeclare());
            }

            if (NumberUtil.isNotNullOrZero(orderPart.getPartType())) {
                log.append("报销类型：");
                log.append(OrderConsts.getPartTypeName(orderPart.getPartType()));
                log.append("，");
            }

            if (orderPart.getPartName() != null) {
                log.append("报销配件：");
                log.append(orderPart.getPartName());
                log.append("，");
            }

            if (orderPart.getPrice() != null && orderPart.getNumber() != null) {
                totalAmount = com.zmn.oms.common.utils.MathUtil.amountMultiplyNumber(orderPart.getPrice(),
                        orderPart.getNumber());
                log.append("数量：");
                log.append(orderPart.getNumber());
                log.append("，单价：");
                log.append(MoneyUtil.parseToYuanEndWithUnit(orderPart.getPrice()));
                log.append("，报销金额：");
                log.append(MoneyUtil.parseToYuanEndWithUnit(totalAmount));
                log.append("，");
            }

            /*
             *  配件报销三种状态：
             *       报销成功：该配件的【报销金额】计算到【总申报金额】中
             *       报销失败：该配件的【报销金额】不参与【总申报金额】计算
             *       不予报销：在日志中写入提示
             * */
            if (Objects.equals(OrderConsts.PART_REIMBURSE_STATUS_SUCCESS, partReimburseDTO.getStatus())) {
                declareAmount += totalAmount;
            } else if (Objects.equals(OrderConsts.PART_REIMBURSE_STATUS_NO, partReimburseDTO.getStatus())) { // 不予报销
                Integer isSystemReimburse = Optional.ofNullable(partReimburseGroupDTO.getSysPartReimburse()).orElse(1);
                if (Objects.equals(isSystemReimburse, GlobalConsts.YES)) {
                    log.append("系统报销：");
                }
                log.append(" 报销总额低于产品组最低报销金额，不予报销；");
            }

            log.append("报销结果：");
            log.append(OrderConsts.getOrderPartReimburseStatusName(partReimburseDTO.getStatus()));
            log.append("\n");
            log.append("\n");
        }

        log.append("申报金额：");
        log.append(MoneyUtil.parseToYuanEndWithUnit(declareAmount));

        if (partReimburseGroupDTO.getOperatorRemark() != null) {
            log.append("\n报销备注：");
            log.append(partReimburseGroupDTO.getOperatorRemark());
        }

        return log.toString();
    }

    /**
     * 开发票
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String invoice(OrderWork dbOrderWork, OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();
        OrderInvoiceDTO invoiceDTO = (OrderInvoiceDTO) omsOperator;
        log.append("发票类型：");
        log.append(Objects.equals(invoiceDTO.getInvoiceNature(), ErpConsts.ORDER_INVOICE_TYPE_PAP) ? "纸质发票" : "电子发票");
        log.append("\n发票抬头：");
        log.append(invoiceDTO.getBuyer());
        log.append("\n纳税人识别号：");
        log.append(invoiceDTO.getBuyerTaxNum());
        log.append("\n发票金额：");
        log.append(this.amount2String(invoiceDTO.getInvoiceAmount()));
        if (StringUtil.isNotBlank(invoiceDTO.getCompanyName())) {
            log.append("\n开票公司：");
            log.append(invoiceDTO.getCompanyName());
        }
        if (Objects.equals(invoiceDTO.getInvoiceNature(), 2)) {
            log.append("\n电子邮箱：");
            log.append(invoiceDTO.getBuyerEmail());
        }
        return log.toString();
    }

    /**
     * 推送开票
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String invoiceRemind(OrderWork dbOrderWork, OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();
        log.append("推送成功");
        return log.toString();
    }

    /**
     * 组装人工优惠
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String discountArtificial(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ZsDiscountDTO discountDTO = (ZsDiscountDTO) omsOperator;
        StringBuilder log = new StringBuilder();

        // 是否删除优惠
        Integer removeDiscount = discountDTO.getRemoveDiscount();
        if (Objects.equals(removeDiscount, GlobalConsts.YES)) {
            if (Objects.equals(discountDTO.getOperateId(), OrderConsts.ORDER_OP_TYPE_DISCOUNT_FREE)) {
                log.append("删除特殊优惠券");
            } else {
                log.append("删除优惠金额");
            }
        } else {
            if (Objects.equals(discountDTO.getOperateId(), OrderConsts.ORDER_OP_TYPE_DISCOUNT_FREE)) {
                log.append(Objects.equals(discountDTO.getDiscountBathId(), DiscountConsts.BATCH_ID_FREE_DISCOUNT_SUB_COMPANY) ? "子公司承担优惠" : "总公司承担优惠");
                log.append("，优惠券折扣：");
                log.append(this.amount2String(discountDTO.getDiscountAmount()) + "折");
            } else {
                if (Objects.equals(discountDTO.getDisCategory(), ThirdPlatEnum.THIRD_COUP_TYPE_MT.getKey())
                        || Objects.equals(discountDTO.getDisCategory(), ThirdPlatEnum.THIRD_COUP_TYPE_KB.getKey())) {
                    log.append(Objects.equals(discountDTO.getDisCategory(), ThirdPlatEnum.THIRD_COUP_TYPE_MT.getKey()) ? "美团" : "口碑");
                    log.append("优惠券：");
                    log.append("券码：").append(discountDTO.getCouponCode());
                    log.append("优惠金额：").append(this.amount2String(discountDTO.getCouponAmount()));
                    log.append("渠道预收：").append(this.amount2String(discountDTO.getCouponPrepayChannelAmount()));
                } else {
                    log.append("人工优惠：");
                    log.append("优惠金额：").append(this.amount2String(discountDTO.getDiscountAmount()));
                }
            }
        }

        String operatorRemark = discountDTO.getOperatorRemark();
        if (StringUtil.isNotBlank(operatorRemark)) {
            log.append("\n缘由：");
            log.append(operatorRemark);
        }

        return log.toString();
    }

    /**
     * 跟单操作
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String track(OrderWork dbOrderWork, OmsOperator omsOperator) {
        OrderTrackDTO orderTrackDTO = (OrderTrackDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        List<OrderTrackDetailDTO> detailDTOList = orderTrackDTO.getDetailDTOList();
        detailDTOList.forEach(detailDTO -> {
            Long trackId = detailDTO.getTrackId();
            String resultContent = detailDTO.getResultContent();
            String mapName = detailDTO.getMapName();
            Integer deleted = detailDTO.getDeleted();

            if (Objects.equals(deleted, GlobalConsts.YES)) {
                log.append("删除跟单:");
                log.append(mapName);
            } else if (Objects.isNull(trackId)) {
                log.append("发起跟单:");
                log.append(mapName);
                log.append(",");
                if (StringUtil.isNotBlank(resultContent)) {
                    log.append("结果:");
                    log.append(resultContent);
                }
            } else if (Objects.nonNull(trackId) && StringUtil.isNotBlank(resultContent)) {
                log.append("跟单:");
                log.append(mapName);
                log.append("，结果:");
                log.append(resultContent);
            }

        });

        omsOperator.setOperatorLogRemark(log.toString());
        return log.toString();
    }

    /**
     * 商家备注
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String factoryRemark(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ZsRemarkDTO remarkDTO = (ZsRemarkDTO) omsOperator;
        String factoryRemark = StringUtils.defaultString(remarkDTO.getFactoryRemark(), "");
        return factoryRemark;
    }

    /**
     * 平台工程师备注
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String platMasterRemark(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ZsRemarkDTO remarkDTO = (ZsRemarkDTO) omsOperator;
        String masterRemark = StringUtils.defaultString(remarkDTO.getMasterRemark(), "");
        return masterRemark;
    }

    /**
     * 平台内部备注
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String remark(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ZsRemarkDTO remarkDTO = (ZsRemarkDTO) omsOperator;
        StringBuilder log = new StringBuilder();

        if (StringUtil.isNotBlank(remarkDTO.getRemark())) {
            log.append(remarkDTO.getRemark());
        }

        return log.toString();
    }

    /**
     * 核配件日志
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String part(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ZsPartDTO partDTO = (ZsPartDTO) omsOperator;
        StringBuilder log = new StringBuilder();

        Integer used = partDTO.getUsed();
        if (Objects.equals(used, GlobalConsts.NO)) {
            return "未使用配件";
        }

        List<ZsPartMasterDTO> partMasterDTOList = partDTO.getPartMasterDTOList();
        partMasterDTOList.forEach(partMasterDTO -> {
            Integer inPartAmount = partMasterDTO.getInPartAmount();
            // 不为0代表使用
            if (inPartAmount != 0) {
                log.append("内采配件 ");
                log.append(partMasterDTO.getMasterName());
                log.append("，内采配件总额：");
                log.append(this.amount2String(partMasterDTO.getInPartAmount()));

                // 配件使用详情
                List<ZsPartMasterDetailDTO> masterDetailVOList = partMasterDTO.getPartMasterDetailDTOList();
                masterDetailVOList.forEach((detail) -> {
                    // 不为0代表使用
                    if (detail.getUseNumber().floatValue() > 0) {
                        log.append("\n");
                        log.append(detail.getPartFullName());
                        log.append(":");
                        log.append(detail.getUseNumber());
                        log.append(detail.getUnit());
                        /*if (conversionMap.containsKey(detail.getPartId())) {
                            ZsPartUnitConversionVO conversionVO = conversionMap.get(detail.getPartId());
                            double number = MathUtil.div(detail.getUseNumber(), conversionVO.getScale(), 2);
                            log.append(number);
                            log.append(conversionVO.getUnit());
                        } else {
                            log.append(detail.getUseNumber());
                            log.append(detail.getUnit());
                        }*/
                        log.append(",");
                        log.append(this.amount2String(detail.getInPartAmount()));
                    }
                });

            }
        });

        return log.toString();
    }

    /**
     * 组装外报配件和运杂费日志
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String partAddReimburse(OrderWork dbOrderWork, OmsOperator omsOperator) {
        AddOrderPartDTO addOrderPartDTO = (AddOrderPartDTO) omsOperator;
        StringBuilder log = new StringBuilder();

        List<OrderPart> list = addOrderPartDTO.getParts();
        int outSourcingAmount = list.stream().mapToInt((e) -> com.zmn.oms.common.utils.MathUtil.amountMultiplyNumber(
                e.getPrice(), e.getNumber())).sum();

        log.append("新增");
        if (Objects.equals(list.get(0).getPartType(), OrderConsts.PART_TYPE_SOURCING_OUT)) {
            log.append("外报配件：");
        } else if (Objects.equals(list.get(0).getPartType(), OrderConsts.PART_TYPE_DELIVER)) {
            log.append("运杂费：");
        }
        log.append(list.get(0).getMasterName());
        log.append("，总额：");
        log.append(this.amount2String(outSourcingAmount));
        list.forEach(orderPart -> {
            log.append("\n");
            log.append(orderPart.getPartFullName());
            log.append(" 数量：");
            log.append(orderPart.getNumber());
            log.append(orderPart.getUnit());
            log.append(" 单价：");
            log.append(this.amount2String(orderPart.getPrice()));
            log.append(" 申报金额：");
            log.append(this.amount2String(orderPart.getDeclarePrice()));
        });

        return log.toString();
    }

    /**
     * 回访日志
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String replyVisit(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ZsReplyVisitDTO replyVisitDTO = (ZsReplyVisitDTO) omsOperator;
        StringBuilder log = new StringBuilder();

        // 评分不为空为有回访评价
        Integer score = replyVisitDTO.getScore();
        if (score != null) {
            log.append("评价：");
            log.append(score);
            log.append("星 ");
            List<KVDict> commentCodeMapList = replyVisitDTO.getCommentCodeMapList();
            if (commentCodeMapList != null && !commentCodeMapList.isEmpty()) {
                commentCodeMapList.forEach((comment) -> {
                    log.append(comment.getText());
                    log.append(" ");
                });
            }
            if (StringUtil.isNotBlank(replyVisitDTO.getCommentContent())) {
                log.append(replyVisitDTO.getCommentContent());
            }
        }

        // 回访内容
        if (log.length() > 0) {
            log.append("\n");
        }

        log.append("回访内容：");
        if (StringUtil.isNotBlank(replyVisitDTO.getReplyContent())) {
            log.append(replyVisitDTO.getReplyContent());
            log.append(" ");
        }

        List<KVDict<Integer>> replyVisitList = replyVisitDTO.getReplyVisitList();
        if (replyVisitList != null && !replyVisitList.isEmpty()) {
            replyVisitList.forEach((comment) -> {
                log.append(comment.getText());
                log.append("：");
                log.append(comment.getExt1());
                log.append(" ");
            });
        }
        return log.toString();
    }

    /**
     * 算账日志
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String account(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ZsSyncAccountDIO accountDTO = (ZsSyncAccountDIO) omsOperator;
        // 工单算账
        StringBuilder log = new StringBuilder();

        // ERP算账日志
        if (StringUtil.isNotBlank(accountDTO.getLogContent())) {
            log.append("ERP算账明细：");
            log.append(accountDTO.getLogContent());
            log.append("\n");
        }

        if (StringUtils.isNotBlank(accountDTO.getOperatorRemark())) {
            // 备注
            log.append("\n备注：");
            log.append(accountDTO.getOperatorRemark());
        }
        return log.toString();
    }

    /**
     * 工程师提成
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String masterRetention(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ZsMasterRetentionDTO masterRetentionDTO = (ZsMasterRetentionDTO) omsOperator;
        // 工单算账
        StringBuilder log = new StringBuilder();//)
        if (masterRetentionDTO.getMasterRetentionAmount() != null && !Objects
                .equals(GlobalConsts.NONE, masterRetentionDTO.getMasterRetentionAmount())) {

            if (Objects.equals(GlobalConsts.PLAT_MARK_SAAS, dbOrderWork.getPlatWork())) {
                log.append("算账提留：");
            } else {
                log.append("工程师提留金额：");
            }

            log.append(this.amount2String(masterRetentionDTO.getMasterRetentionAmount()));
            log.append("\n");
        }

        if (StringUtils.isNotBlank(masterRetentionDTO.getOperatorRemark())) {
            // 备注
            log.append("备注：");
            log.append(masterRetentionDTO.getOperatorRemark());
        }
        return log.toString();

    }

    /**
     * 取消
     *
     * @param omsOperator
     * @return
     */
    String cancel(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ZsCancelDTO cancelDTO = (ZsCancelDTO) omsOperator;
        List<OrderRemarkDetailDTO> detailDTOList = cancelDTO.getDetailDTOList();

        StringBuilder log = new StringBuilder();

        Integer reviewStatus = cancelDTO.getReviewStatus();
        if (Objects.nonNull(reviewStatus) && Objects.equals(reviewStatus, OrderConsts.REVIEW_STATUS_FAIL)) {
            log.append("审核失败。");
            return log.toString();
        }

        if (Objects.equals(cancelDTO.getRefundCancel(), GlobalConsts.YES)) {
            log.append("退款后，自动取消。");
        }
        log.append("取消缘由：");
        if (StringUtils.isNotBlank(cancelDTO.getContent())) {
            log.append(StringUtils.defaultString(cancelDTO.getContent()));
        }

        if (Objects.equals(cancelDTO.getOperatorType(), GlobalConsts.OPERATE_USER_TYPE_USER)) {
            log.append("用户取消订单");
        }

        if (CollectionUtils.isNotEmpty(detailDTOList)) {
            detailDTOList.forEach(detail -> {
                log.append(",");
                log.append(detail.getMapName());
            });
        }

        String telephone = "17777777777";
        String remark = "啄木鸟测试";
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(cancelDTO.getOrderId());
        if (orderDetail != null && (Objects.equals(orderDetail.getTelephone(), telephone) || Objects.equals(orderDetail.getRemark(), remark))) {
            log.append(",重复");
        }

        Long originalCode = cancelDTO.getOriginalCode();
        if (originalCode != null) {
            log.append("\n重复源单号：");
            log.append(originalCode);
        }
        return log.toString();
    }

    /**
     * 收单
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String checkout(OrderWork dbOrderWork, OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();
        ZsCheckOutDTO zsCheckoutDto = (ZsCheckOutDTO) omsOperator;

        List<ServiceItemVO> itemVOS = zsCheckoutDto.getServiceItemVOList();
        if (CollectionUtil.isNotNullOrEmpty(itemVOS)) {
            itemVOS.forEach(item -> {
                log.append(item.getServItemName())
                        .append("：")
                        .append(MoneyUtil.parseToYuanStr(item.getOldInternalSettlementPrice()))
                        .append("-")
                        .append(MoneyUtil.parseToYuanStr(item.getInternalSettlementPrice()))
                        .append("\n");
            });
        }

        if (!NumberUtil.isNullOrZero(zsCheckoutDto.getResultStatus())) {
            log.append("工单结果：");
            log.append(OrderStatusConsts.getWorkResultStatusName(zsCheckoutDto.getResultStatus()));
            log.append("\n");
        }
        if (zsCheckoutDto.getIsAutoCheckOut()) {
            log.append("收单方式：系统自动收单；");
            log.append("\n");
        }
        if (StringUtils.isNotBlank(zsCheckoutDto.getOperatorRemark())) {
            log.append("备注：");
            log.append(zsCheckoutDto.getOperatorRemark());
        }
        return log.toString();
    }

    /**
     * 改渠道
     *
     * @param dbOrderWork 数据库工单
     * @param omsOperator 操作对象
     */
    String updateChannel(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ChannelUpdateDTO updateDTO = (ChannelUpdateDTO) omsOperator;
        String targetChannelName = updateDTO.getChannelName();
        String srcChannelName = dbOrderWork.getChannelName();
        String targetOuterId = updateDTO.getOuterId();
        String srcOuterId = dbOrderWork.getOuterId();
        String currentRemark = updateDTO.getOperatorRemark();
        String log = String.format("渠道：%s -> %s，渠道订单号：%s -> %s，缘由：%s", srcChannelName,
                StringUtils.defaultString(targetChannelName), StringUtils.defaultString(srcOuterId),
                StringUtils.defaultString(targetOuterId), currentRemark);
        return log;
    }

    /**
     * 改渠道费
     *
     * @param dbOrderWork 数据库工单
     * @param omsOperator 操作对象
     */
    String updateChannelAmount(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ZsChannelAmountDTO zsChannelAmountDTO = (ZsChannelAmountDTO) omsOperator;
        return String.format("渠道费：%s -> %s，缘由：%s", MoneyUtil.parseToYuanStr(dbOrderWork.getChannelAmount()),
                Objects.equals(zsChannelAmountDTO.getDeleteChannelAmount(), GlobalConsts.YES) ?
                        "删除渠道费" :
                        MoneyUtil.parseToYuanStr(zsChannelAmountDTO.getChannelAmount()),
                zsChannelAmountDTO.getOperatorRemark());
    }

    /**
     * 派单
     *
     * @param dbOrderWork 数据库工单
     * @param omsOperator 操作对象
     */
    String distribute(OrderWork dbOrderWork, OmsOperator omsOperator) {
        OrderDistributeDTO distributeDTO = (OrderDistributeDTO) omsOperator;
        StringBuilder log = new StringBuilder();

        // 强制派单记录日志
        if (Objects.equals(distributeDTO.getMandatory(), GlobalConsts.YES)) {
            log.append("[强制派单]");
        }

        if (!Objects.equals(dbOrderWork.getMasterId(), distributeDTO.getMasterId())) {

            // 查询工程师信息
            // todo fubiao
            logger.info("distribute#getEngineerDetailById 入参 [{}]", distributeDTO.getMasterId());
            ResponseDTO<ForeignEngineerDetailInfoDRO> cacheEngineerByEngineerId = engineerListRemoteService
                    .getEngineerDetailById(distributeDTO.getMasterId());
            logger.info("distribute#getEngineerDetailById 出参 [{}]", JSON.toJSONString(cacheEngineerByEngineerId));
            ForeignEngineerDetailInfoDRO baseEngineerDRO = cacheEngineerByEngineerId.getData();
            if (!cacheEngineerByEngineerId.isSuccess() || baseEngineerDRO == null) {
                return null;
            }

            boolean auto = false;
            // 自动派单文案
            if (distributeDTO.isAutoDistribute()) {
                log.append("[");

                if (distributeDTO.getAutoDistributeCount() != null && distributeDTO.getAutoDistributeCount() > 1) {
                    log.append("再次自动派单");
                } else {
                    log.append("自动派单");
                }

                log.append("]");
                auto = true;
            }

            // 抢单
            if (Objects.equals(distributeDTO.getGrabType(), GlobalConsts.YES)) {
                log.append("[工程师抢单]");
            }

            // 派单方式文案
            if (StringUtils.isNotBlank(distributeDTO.getDistributeTypeText())) {
                log.append("[");
                log.append(distributeDTO.getDistributeTypeText());
                log.append("]");
            }

            // 工程师信息
            distributeDTO.setMasterName(baseEngineerDRO.getRealName());
            distributeDTO.setMasterPhone(baseEngineerDRO.getMobile());

            //查询工程师分组信息
            if (distributeDTO.getMasterId() != null) {
                // 设置工程师产品分组
                // todo fubiao
                logger.info("distribute#getProductGroupByEngineerIdAndBizType 入参 [{}] [{}]", distributeDTO.getMasterId(), dbOrderWork.getBizType());
                ResponseDTO<Option<Integer>> responseDTO = engineerCooperateInfoListRemoteService.getProductGroupByEngineerIdAndBizType(distributeDTO.getMasterId(),
                        dbOrderWork.getBizType());
                logger.info("distribute#getProductGroupByEngineerIdAndBizType 出参 [{}]", JSON.toJSONString(responseDTO));
                if (responseDTO.isSuccess()) {
                    distributeDTO.setMasterGroupName(StringUtils.defaultString(responseDTO.getData().getLabel()));
                }
            }
            log.append(dbOrderWork.getMasterName()).append("->");
            if (StringUtil.isNotBlank(distributeDTO.getMasterGroupName())) {
                log.append(distributeDTO.getMasterGroupName()).append("-");
            }

            // 工程师名称（网格化派单记录直营和主网格）
            String masterName;

            // 平台直派
            if (Objects.equals(distributeDTO.getDistributeWay(), OrderDistributeConsts.DISTRIBUTE_WAY_PLAT)) {

                // 工程师后缀
                String strAgent;
                if (Objects.equals(baseEngineerDRO.getCooperationType(), GlobalConsts.NO)) {
                    strAgent = "直营";
                } else {
                    strAgent = "非直营";
                }

                // 是自动派单
                if (distributeDTO.isAutoDistribute()) {

                    do {

                        // 是返修原工程师规则派出
                        if (Objects.equals(distributeDTO.getDistributeRule(), OrderDistributeConsts.DISTRIBUTE_RULE_REWORK)) {
                            masterName = String.format("%s[%s]", distributeDTO.getMasterName(), strAgent);
                            break;
                        }

                        // 网格内派单
                        if (Objects.equals(distributeDTO.getDistributeGrid(), OrderDistributeConsts.DISTRIBUTE_GRID_IN)) {

                            String strGrid;
                            if (Objects.equals(distributeDTO.getWorkspaceType(), OrderDistributeConsts.WORKSPACE_TYPE_MAIN)) {
                                strGrid = "主网格";
                            } else {
                                strGrid = "支援网格";
                            }

                            masterName = String.format("%s[%s][%s]", distributeDTO.getMasterName(), strAgent, strGrid);

                            break;
                        }

                        if (NumberUtil.isNotNullOrZero(distributeDTO.getOrderCenterDistance())) {
                            // 跨网格派单，转换为公里显示
                            double distance = distributeDTO.getOrderCenterDistance() / 1000.0D;
                            masterName = String.format("%s[%s][系统跨网格][跨网格派单距离-%.1fkm]", distributeDTO.getMasterName(), strAgent, distance);
                        } else {
                            masterName = String.format("%s[%s]", distributeDTO.getMasterName(), strAgent);
                        }

                    } while (false);

                }
                // 人工派单
                else {
                    // 网格外派单
                    if (Objects.equals(distributeDTO.getDistributeGrid(), OrderDistributeConsts.DISTRIBUTE_GRID_OUT)) {
                        masterName = String.format("%s[%s][人工网格外]", distributeDTO.getMasterName(), strAgent);
                    } else {
                        masterName = String.format("%s[%s]", distributeDTO.getMasterName(), strAgent);
                    }
                }

            }
            // 服务商派单
            else {
                masterName = distributeDTO.getMasterName();
            }

            log.append(masterName);

            // 是否最优库存
            if (MasterStockTypeEnum.OPTIMAL_STOCK.getCode().equals(distributeDTO.getStockType())) {
                log.append("[最优库存]");
            }

            // 是否录单预派
            if (distributeDTO.isPreDistribute()) {
                log.append("[录单预派]");
            }

            if (auto && Objects.nonNull(distributeDTO.getOperateTime())
                    && OrderDistributeConsts.distributeSnapshotList.contains(distributeDTO.getDistributeRule())) {
                log.append(" <a name='distributeSnapshot' style='color: blue;cursor: pointer;'>详情</a>");
            }

            // 清空优惠
            boolean updateStatusToConfirm = !Objects.equals(dbOrderWork.getMasterId(), distributeDTO.getMasterId()) && (
                    Objects.equals(dbOrderWork.getStatus(), OrderStatusConsts.WORK_STATUS_TAKE) || Objects
                            .equals(dbOrderWork.getStatus(), OrderStatusConsts.WORK_STATUS_VISIT));

            if (updateStatusToConfirm && Objects.nonNull(dbOrderWork.getDiscountAmount())) {
                List<OrderDiscount> discountList = orderDiscountService.listByOrderId(distributeDTO.getOrderId());
                List<Integer> artificial = Arrays.asList(FicoConsts.ORDER_IN_DISCOUNT_CATEG_ARTIFICIAL_OPERATOR,
                        FicoConsts.ORDER_IN_DISCOUNT_CATEG_ARTIFICIAL_MASTER);
                int discountAmount = discountList.stream().filter(e -> !artificial.contains(e.getCateg()))
                        .mapToInt(OrderDiscount::getAmount).sum();
                int cleanDiscountAmount = dbOrderWork.getDiscountAmount() - discountAmount;
                if (cleanDiscountAmount > 0) {
                    log.append("\n");
                    log.append(String.format("清空优惠：%s，缘由：重新派单", this.amount2String(cleanDiscountAmount)));
                }
            }

            // 小号绑定：用户电话：xx - 小号：xx - 工程师电话：xx（有多个，则“；”隔开，下同）；绑定成功/失败
            OrderChangeRecord changeRecordByOrderId = orderChangeRecordService.getChangeRecordByOrderId(dbOrderWork.getOrderId());
            OrderDetail orderDetail = orderDetailService.findOrderDetailByKeySrcMaster(dbOrderWork.getOrderId());
            // 判断是否需要加小号相关日志
            if (orderDetail.getBindStatus() != 0) {
                // 首次派单
                if (changeRecordByOrderId == null || changeRecordByOrderId.getDistributeCount() == 0) {
                    if (orderDetail.getBindStatus() == OrderConsts.BIND_STATUS_BIND) {
                        log.append("\n");
                        log.append("[小号绑定：");
                        processBindLog(log, orderDetail, baseEngineerDRO.getMobile(), dbOrderWork);
                    }
                } else {
                    // 改派 - 转绑log记录
                    if (orderDetail.getBindStatus() == OrderConsts.BIND_STATUS_BIND) {
                        log.append("\n");
                        log.append("改派后小号及工程师电话变更为:");
                        processBindLog(log, orderDetail, baseEngineerDRO.getMobile(), dbOrderWork);
                    }
                }
            }

            // 派单关联多师傅日志文案
            if (StringUtils.isNotBlank(distributeDTO.getRelateMultiMasterText())) {
                log.append("\n");
                log.append(distributeDTO.getRelateMultiMasterText());
            }

            // 派单关联工单文案
            if (StringUtils.isNotBlank(distributeDTO.getDistributeRelateWorkText())) {
                log.append("\n");
                log.append(distributeDTO.getDistributeRelateWorkText());
            }
        }

        // 网格化派单记录分单日志
        if (Objects.equals(distributeDTO.getDistributeWay(), OrderDistributeConsts.DISTRIBUTE_WAY_PLAT)) {
            log.append("\n分单：")
                    .append("执行子公司：")
                    .append(distributeDTO.getCompanyName())
                    .append("，执行服务商：")
                    .append(distributeDTO.getManageCompanyName())
                    .append("\n网格ID：")
                    .append(distributeDTO.getGridId())
                    .append("，网格名称：")
                    .append(distributeDTO.getGridName());
        }

        // 改派缘由
        if (NumberUtil.isNotNullOrZero(distributeDTO.getDistributeReasonId())) {
            log.append("\n改派缘由：").append(distributeDTO.getDistributeReason());
            log.append("\n责任工程师：");
            if (Objects.equals(distributeDTO.getLiableType(), OrderConsts.ORDER_LIABLE_TYPE_SOURCE_MASTER)) {
                OrderChangeRecord changeRecord = orderChangeRecordService.getChangeRecordByOrderId(distributeDTO.getOrderId());
                if (changeRecord != null) {
                    log.append("原工程师-").append(StringUtils.defaultIfBlank(changeRecord.getLiableMasterName(), distributeDTO.getMasterName()));
                } else {
                    log.append("当前工程师-").append(distributeDTO.getMasterName());
                }
            } else {
                log.append("当前工程师-").append(distributeDTO.getMasterName());
            }
        }

        return log.toString();
    }

    /**
     * 领单
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String takeOrder(OrderWork dbOrderWork, OmsOperator omsOperator) {
        MasterTakeDTO masterTakeDTO = (MasterTakeDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        if (Objects.equals(masterTakeDTO.getGrabType(), GlobalConsts.YES)) {
            log.append("自动领单；");
        }
        log.append(StringUtils.defaultString(masterTakeDTO.getServiceItemLog()));
        return log.toString();
    }

    /**
     * 确认
     *
     * @param dbOrderWork 数据库工单
     * @param omsOperator 操作对象
     */
    String confirm(OrderWork dbOrderWork, OmsOperator omsOperator, OrderLog orderLog) {
        if (omsOperator instanceof OrderDTO) {
            return this.updateOrder(dbOrderWork, omsOperator, orderLog);
        } else { // 自动确认无需日志
            return "";
        }
    }

    /**
     * 改工单
     *
     * @param dbOrderWork 数据库工单
     * @param omsOperator 操作对象
     */
    String updateOrder(OrderWork dbOrderWork, OmsOperator omsOperator, OrderLog orderLog) {
        OrderDTO orderDTO = (OrderDTO) omsOperator;

        // 历史数据
        dbOrderWork = orderDTO.getDbOrderWork();
        OrderDetail dbOrderDetail = orderDTO.getDbOrderDetail();
        OrderFactory dbOrderFactory = orderDTO.getDbOrderFactory();
        List<OrderProduct> dbOrderProductList = orderDTO.getDbOrderProductList();

        // 修改数据
        OrderDetail orderDetail = orderDTO.getOrderDetail();
        List<OrderProduct> orderProductList = orderDTO.getOrderProductList();
        OrderWork orderWork = orderDTO.getOrderWork();
        OrderFactory orderFactory = orderDTO.getOrderFactory();

        List<String> logList = Lists.newArrayList();

        // 手机号码变更
        String dbTelephone = StringUtils.defaultString(dbOrderDetail.getTelephone());
        String telephone = StringUtils.defaultString(orderDetail.getTelephone());
        if (!StringUtils.equals(dbTelephone, telephone)) {
            logList.add(String.format("手机号：%s->%s", MobileUtil.formatHideTel(dbTelephone), MobileUtil.formatHideTel(telephone)));
        }
        String dbTelephone2 = StringUtils.defaultString(dbOrderDetail.getTelephone2());
        String telephone2 = StringUtils.defaultString(orderDetail.getTelephone2());
        if (!StringUtils.equals(dbTelephone2, telephone2)) {
            logList.add(String.format("手机号02：%s->%s", MobileUtil.formatHideTel(dbTelephone2), MobileUtil.formatHideTel(telephone2)));
        }
        String dbTelephone3 = StringUtils.defaultString(dbOrderDetail.getTelephone3());
        String telephone3 = StringUtils.defaultString(orderDetail.getTelephone3());
        if (!StringUtils.equals(dbTelephone3, telephone3)) {
            logList.add(String.format("手机号03：%s->%s", MobileUtil.formatHideTel(dbTelephone3), MobileUtil.formatHideTel(telephone3)));
        }

        // 姓名
        String dbContactName = StringUtils.defaultString(dbOrderDetail.getContactName());
        String contactName = StringUtils.defaultString(orderDetail.getContactName());
        if (!StringUtils.equals(dbContactName, contactName)) {
            logList.add(String.format("联系人：%s->%s", dbContactName, contactName));
        }
        // 性别
        if (orderDetail.getGender() != null && !Objects.equals(dbOrderDetail.getGender(), orderDetail.getGender())) {
            logList.add(String.format("性别：%s->%s", GlobalDict.getGender(dbOrderDetail.getGender()),
                    GlobalDict.getGender(orderDetail.getGender())));
        }
        // 地址pinDuoDuoShopProductMappingService
        if (!Objects.equals(dbOrderWork.getCityId(), orderWork.getCityId()) || !Objects
                .equals(dbOrderDetail.getLatitude(), orderDetail.getLatitude()) || !Objects
                .equals(dbOrderDetail.getLongitude(), orderDetail.getLongitude())) {
            StringBuilder sbAddress = new StringBuilder();
            sbAddress.append(dbOrderDetail.getProvinceName()).append(dbOrderDetail.getCityName())
                    .append(dbOrderDetail.getCountyName()).append(StringUtils.defaultString(dbOrderDetail.getStreet()))
                    .append(StringUtils.defaultString(dbOrderDetail.getAddress())).append("；经纬度：")
                    .append(dbOrderDetail.getLongitude()).append(",").append(dbOrderDetail.getLatitude());
            sbAddress.append("->");
            sbAddress.append(orderDetail.getProvinceName()).append(orderDetail.getCityName())
                    .append(StringUtils.defaultString(orderDetail.getCountyName())).append(StringUtils.defaultString(orderDetail.getStreet()))
                    .append(StringUtils.defaultString(orderDetail.getAddress())).append("；经纬度：")
                    .append(orderDetail.getLongitude()).append(",").append(orderDetail.getLatitude());
            logList.add(sbAddress.toString());
        } else if (!Objects.equals(dbOrderDetail.getAddress(), orderDetail.getAddress())) {
            logList.add(dbOrderDetail.getAddress() + "->" + orderDetail.getAddress());
        }

        // 渠道
        if (orderWork.getChannelId() != null && !Objects.equals(dbOrderWork.getChannelId(), orderWork.getChannelId())) {
            logList.add(String.format("渠道：%s->%s", StringUtils.defaultString(dbOrderWork.getChannelName()),
                    StringUtils.defaultString(orderWork.getChannelName())));
        }

        // 订单类型
        if (orderWork.getType() != null && !Objects.equals(dbOrderWork.getType(), orderWork.getType())) {
            logList.add(String.format("类型：%s->%s", OrderConsts.getOrderTypeName(dbOrderWork.getType()),
                    OrderConsts.getOrderTypeName(orderWork.getType())));
        }

        // 服务分类
        if (!Objects.equals(dbOrderDetail.getServCategId(), orderDetail.getServCategId())) {
            logList.add(String.format("服务分类：%s->%s", StringUtils.defaultString(dbOrderDetail.getServCategName()),
                    StringUtils.defaultString(orderDetail.getServCategName())));
        }

        // 服务产品
        if (Objects.equals(dbOrderWork.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_FACTORY)) {

            if (!Objects.equals(dbOrderFactory.getFcProductId(), orderFactory.getFcProductId()) || !Objects
                    .equals(dbOrderFactory.getFcProductNumber(), orderFactory.getFcProductNumber())) {
                StringBuilder sb = new StringBuilder();
                sb.append("厂商产品：");
                sb.append(dbOrderFactory.getFcProductName()).append("x").append(dbOrderFactory.getFcProductNumber());
                sb.append("->");
                sb.append(orderFactory.getFcProductName()).append("x").append(orderFactory.getFcProductNumber());
                logList.add(sb.toString());
            }

        }
        if (this.isProcessOrderProduct(orderProductList, dbOrderProductList)) {
            StringBuilder sb = new StringBuilder();
            sb.append("服务产品：");
            List<String> productListLog = Lists.newArrayList();
            dbOrderProductList.forEach(item -> {
                productListLog.add(this.getProductChangeLog(item));
            });
            sb.append(StringUtils.join(productListLog, "；"));
            productListLog.clear();
            sb.append("->");
            orderProductList.forEach(item -> {
                productListLog.add(this.getProductChangeLog(item));
            });
            sb.append(StringUtils.join(productListLog, "；"));
            logList.add(sb.toString());
        }

        // 预约时间
        if (dbOrderWork.getDutyTime() == null && orderWork.getDutyTime() != null) {
            logList.add(
                    String.format("预约时间：->%s", DateUtil.toString(orderWork.getDutyTime(), DateUtil.FORMAT_DATETIME)));
        } else if (dbOrderWork.getDutyTime() != null && orderWork.getDutyTime() == null) {
            logList.add(String.format("预约时间：%s-> ",
                    DateUtil.toString(dbOrderWork.getDutyTime(), DateUtil.FORMAT_DATETIME)));
        } else {
            String dbDutyTime = DateUtil.toString(dbOrderWork.getDutyTime(), DateUtil.FORMAT_DATETIME);
            String dutyTime = DateUtil.toString(orderWork.getDutyTime(), DateUtil.FORMAT_DATETIME);
            if (!Objects.equals(dbDutyTime, dutyTime)) {
                logList.add(String.format("预约时间：%s->%s", dbDutyTime, dutyTime));
            }
        }
        // 预约失败
        if (Objects.equals(OrderDutyConsts.DUTY_STATUS_FAIL, orderWork.getDutyStatus())) {
            //从无到有
            if (((dbOrderWork.getNextContactTime() == null && orderWork.getNextContactTime() != null)) ||
                    !Objects.equals(dbOrderWork.getDutyStatus(), orderWork.getDutyStatus())
            ) {
                logList.add(String.format("预约失败：->下次联系时间：%s，失败原因：%s",
                        DateUtil.toString(orderWork.getNextContactTime(), DateUtil.FORMAT_DATETIME),
                        OrderDutyConsts.getDutyFailedReasonName(orderWork.getDutyFailCode())));
            }
            //从有到有
            else if (dbOrderWork.getNextContactTime() != null && orderWork.getNextContactTime() != null) {
                if (!Objects.equals(dbOrderWork.getNextContactTime(), orderWork.getNextContactTime())) {
                    logList.add(String.format("预约失败：->下次联系时间：%s->%s，失败原因：%s",
                            DateUtil.toString(dbOrderWork.getNextContactTime(), DateUtil.FORMAT_DATETIME),
                            DateUtil.toString(orderWork.getNextContactTime(), DateUtil.FORMAT_DATETIME),
                            OrderDutyConsts.getDutyFailedReasonName(orderWork.getDutyFailCode())));
                }
            }
        }

        // 订单备注
        String dbRemark = StringUtils.defaultString(dbOrderDetail.getRemark());
        String remark = StringUtils.defaultString(orderDetail.getRemark());
        if (!Objects.equals(dbRemark, remark)) {
            logList.add(String.format("备注：%s->%s", dbRemark, remark));
        }

        //网格信息变更
        if (zsDistributeWorkBService.isGridDistributeByConfig(orderWork)) {
            if (!Objects.equals(orderDetail.getGridId(), dbOrderDetail.getGridId())) {
                StringBuilder builder = new StringBuilder();
                builder.append("网格：");
                if (!Objects.equals(dbOrderDetail.getGridId(), GlobalConsts.NONE)) {
                    builder.append(dbOrderDetail.getGridName()).append("/").append(dbOrderDetail.getGridId());
                }
                builder.append("->");
                if (!Objects.equals(orderDetail.getGridId(), GlobalConsts.NONE)) {
                    builder.append(orderDetail.getGridName()).append("/").append(orderDetail.getGridId());
                }
                logList.add(builder.toString());
            }
        }

        // 测试单
        if (orderWork.getTest() != null && !Objects.equals(dbOrderWork.getTest(), orderWork.getTest())) {
            StringBuilder builder = new StringBuilder();
            builder.append("测试单：");
            builder.append(Objects.equals(dbOrderWork.getTest(), GlobalConsts.YES) ? "是" : "否");
            builder.append("->");
            builder.append(Objects.equals(orderWork.getTest(), GlobalConsts.YES) ? "是" : "否");
            logList.add(builder.toString());
        }

        // 渠道单号
        if (orderWork.getOuterId() != null && !Objects.equals(dbOrderWork.getOuterId(), orderWork.getOuterId())) {
            StringBuilder builder = new StringBuilder();
            builder.append("渠道单号：");
            builder.append(dbOrderWork.getOuterId());
            builder.append("->");
            builder.append(orderWork.getOuterId());
            logList.add(builder.toString());
        }

        return StringUtils.join(logList, '\n');
    }

    /**
     * 修改地址
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    String updateOrderAddress(OrderWork dbOrderWork, OmsOperator omsOperator) {
        OrderDTO orderDTO = (OrderDTO) omsOperator;

        // 历史数据
        dbOrderWork = orderDTO.getDbOrderWork();
        OrderDetail dbOrderDetail = orderDTO.getDbOrderDetail();

        // 修改数据
        OrderDetail orderDetail = orderDTO.getOrderDetail();
        OrderWork orderWork = orderDTO.getOrderWork();
        List<String> logList = Lists.newArrayList();

        if (BooleanUtils.isNotTrue(orderDTO.getUpdateAddress())) {
            // 手机号码变更
            String dbTelephone = StringUtils.defaultString(dbOrderDetail.getTelephone());
            String telephone = StringUtils.defaultString(orderDetail.getTelephone());
            if (!StringUtils.equals(dbTelephone, telephone)) {
                logList.add(String.format("手机号：%s->%s", MobileUtil.formatHideTel(dbTelephone), MobileUtil.formatHideTel(telephone)));
            }
            String dbTelephone2 = StringUtils.defaultString(dbOrderDetail.getTelephone2());
            String telephone2 = StringUtils.defaultString(orderDetail.getTelephone2());
            if (!StringUtils.equals(dbTelephone2, telephone2)) {
                logList.add(String.format("手机号02：%s->%s", MobileUtil.formatHideTel(dbTelephone2), MobileUtil.formatHideTel(telephone2)));
            }
            String dbTelephone3 = StringUtils.defaultString(dbOrderDetail.getTelephone3());
            String telephone3 = StringUtils.defaultString(orderDetail.getTelephone3());
            if (!StringUtils.equals(dbTelephone3, telephone3)) {
                logList.add(String.format("手机号03：%s->%s", MobileUtil.formatHideTel(dbTelephone3), MobileUtil.formatHideTel(telephone3)));
            }

            // 姓名
            String dbContactName = StringUtils.defaultString(dbOrderDetail.getContactName());
            String contactName = StringUtils.defaultString(orderDetail.getContactName());
            if (!StringUtils.equals(dbContactName, contactName)) {
                logList.add(String.format("联系人：%s->%s", dbContactName, contactName));
            }
        }
        // 地址
        if (!Objects.equals(dbOrderWork.getCityId(), orderWork.getCityId()) || !Objects
                .equals(dbOrderDetail.getLatitude(), orderDetail.getLatitude()) || !Objects
                .equals(dbOrderDetail.getLongitude(), orderDetail.getLongitude())) {
            StringBuilder sbAddress = new StringBuilder();
            sbAddress.append(dbOrderDetail.getProvinceName()).append(dbOrderDetail.getCityName())
                    .append(dbOrderDetail.getCountyName()).append(StringUtils.defaultString(dbOrderDetail.getStreet()))
                    .append(StringUtils.defaultString(dbOrderDetail.getAddress())).append("；经纬度：")
                    .append(dbOrderDetail.getLongitude()).append(",").append(dbOrderDetail.getLatitude());
            sbAddress.append("->");
            sbAddress.append(StringUtils.defaultString(orderDetail.getProvinceName(), dbOrderDetail.getProvinceName()))
                    .append(StringUtils.defaultString(orderDetail.getCityName(), dbOrderDetail.getCityName()))
                    .append(orderDetail.getCountyName()).append(StringUtils.defaultString(orderDetail.getStreet()))
                    .append(StringUtils.defaultString(orderDetail.getAddress())).append("；经纬度：")
                    .append(orderDetail.getLongitude()).append(",").append(orderDetail.getLatitude());
            logList.add(sbAddress.toString());
        } else if (!Objects.equals(dbOrderDetail.getAddress(), orderDetail.getAddress())) {
            logList.add(dbOrderDetail.getAddress() + "->" + orderDetail.getAddress());
        }

        if (BooleanUtils.isNotTrue(orderDTO.getUpdateAddress())) {
            // 订单备注
            String dbRemark = StringUtils.defaultString(dbOrderDetail.getRemark());
            String remark = StringUtils.defaultString(orderDetail.getRemark());
            if (!Objects.equals(dbRemark, remark)) {
                logList.add(String.format("备注：%s->%s", dbRemark, remark));
            }
        }

        //网格信息变更
        if (zsDistributeWorkBService.isGridDistributeByConfig(orderWork)) {
            if (!Objects.equals(orderDetail.getGridId(), dbOrderDetail.getGridId())) {
                StringBuilder builder = new StringBuilder();
                builder.append("网格：");
                if (!Objects.equals(dbOrderDetail.getGridId(), GlobalConsts.NONE)) {
                    builder.append(dbOrderDetail.getGridName()).append("/").append(dbOrderDetail.getGridId());
                }
                builder.append("->");
                if (!Objects.equals(orderDetail.getGridId(), GlobalConsts.NONE)) {
                    builder.append(orderDetail.getGridName()).append("/").append(orderDetail.getGridId());
                }
                logList.add(builder.toString());
            }
        }

        return StringUtils.join(logList, '\n');

    }

    /**
     * 获取产品log
     *
     * @param orderProduct
     * @return
     */
    String getProductChangeLog(OrderProduct orderProduct) {
        StringBuilder remarkLog = new StringBuilder();
        if (StringUtils.isNotBlank(orderProduct.getFault())) {
            try {
                List<MapDTO> faultList = JSON.parseArray(orderProduct.getFault(), MapDTO.class);
                remarkLog.append(StringUtils
                        .join(Optional.ofNullable(faultList).orElse(Lists.newArrayListWithCapacity(0)).stream()
                                .map(MapDTO::getMapName).collect(Collectors.toList()), "，"));
            } catch (Exception ex) {
            }
        }
        if (StringUtils.isBlank(orderProduct.getRemark())) {
            remarkLog.append("，").append(orderProduct.getRemark());
        }
        return String.format("前台产品[%s]-后台产品[%s],数量:%s品牌:%s%s",
                StringUtils.defaultIfBlank(orderProduct.getShowProductName(), "-"),
                StringUtils.defaultIfBlank(orderProduct.getProductName(), "-"), orderProduct.getNumber(),
                StringUtils.defaultIfBlank(orderProduct.getBrandName(), "-"),
                remarkLog.length() > 0 ? String.format("（故障：%s）", remarkLog.toString()) : "");
    }

    /**
     * 判断是产品是否有变化
     *
     * @param orderProductList
     * @param dbOrderProductList
     * @return 变化：true，没有变化：false
     */
    private boolean isProcessOrderProduct(List<OrderProduct> orderProductList, List<OrderProduct> dbOrderProductList) {
        if (orderProductList.size() != dbOrderProductList.size()) {
            return true;
        }

        for (OrderProduct item : orderProductList) {
            for (OrderProduct orderProduct : dbOrderProductList) {
                boolean isNotChanged = (Objects.equals(orderProduct.getProductId(), item.getProductId()) && Objects
                        .equals(orderProduct.getShowProductId(), item.getShowProductId())) && Objects
                        .equals(orderProduct.getBrandId(), item.getBrandId()) && Objects
                        .equals(orderProduct.getNumber(), item.getNumber()) && Objects
                        .equals(orderProduct.getRemark(), item.getRemark()) && Objects
                        .equals(orderProduct.getFault(), item.getFault());
                if (!isNotChanged) {
                    return true;
                }
            }
        }
        return false;
    }

    String leave(OmsOperator omsOperator) {
        StringBuilder sb = new StringBuilder();

        sb.append("工程师出发");

        if (omsOperator.getLongitude() == null || omsOperator.getLatitude() == null) {
            return sb.toString();
        }

        sb.append(", (").append(omsOperator.getLongitude()).append(",").append(omsOperator.getLatitude()).append(")");

        return sb.toString();
    }

    /**
     * 上门
     *
     * @param dbOrderWork 数据库工单
     * @param omsOperator 操作对象
     */
    String visit(OrderWork dbOrderWork, OmsOperator omsOperator) {
        StringBuilder sb = new StringBuilder();
        if (StringUtil.isNotBlank(omsOperator.getOperatorLogRemark())) {
            sb.append(omsOperator.getOperatorLogRemark()).append("；");
        }
        if (StringUtil.isNotBlank(omsOperator.getOperatorRemark())) {
            sb.append(omsOperator.getOperatorRemark()).append("；");
        }

        Double distance = null;
        do {
            if (omsOperator.getLongitude() == null || omsOperator.getLatitude() == null) {
                break;
            }

            OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(dbOrderWork.getOrderId());
            if (orderDetail.getLongitude() == null || orderDetail.getLatitude() == null) {
                break;
            }

            distance = MathUtil.GetDistance(orderDetail.getLongitude(), orderDetail.getLatitude(), omsOperator.getLongitude(), omsOperator.getLatitude());
        } while (false);

        // 记录上门距离
        sb.append("上门距离：");

        String distanceLog;
        if (distance == null) {
            distanceLog = "位置离线，";
        } else {
            distanceLog = String.format("%.2f KM，", distance / 1000);
        }

        sb.append(distanceLog);
        sb.append("上门时间：");
        sb.append(DateUtil.getNowFormatted());

        return sb.toString();
    }

    /**
     * 申请多次上门
     *
     * @param dbOrderWork 数据库工单
     * @param omsOperator 操作对象
     */
    String applyMultipleVisit(OrderWork dbOrderWork, OmsOperator omsOperator) {
        StringBuilder sb = new StringBuilder();
        OrderMultipleVisitDTO multipleVisitDTO = (OrderMultipleVisitDTO) omsOperator;

        sb.append("上门类型：").append(OrderVisitStatusConsts.getVisitTypeName(multipleVisitDTO.getVisitType()));
        if (NumberUtil.isNotNullOrZero(multipleVisitDTO.getAmount())) {
            sb.append("\n金额类型：").append(OrderPayConsts.getAmountTypeName(multipleVisitDTO.getAmountType()));
            sb.append("\n金额：").append(MoneyUtil.parseToYuanEndWithUnit(Optional.ofNullable(multipleVisitDTO.getAmount()).orElse(0)));
        }
        sb.append("\n预计下次上门时间：").append(DateUtil.dateFormatToString(multipleVisitDTO.getExpectVisitTime(), DateUtil.FORMAT_DEFAULT));
        sb.append("\n备注：").append(StringUtils.defaultString(multipleVisitDTO.getRemark()));
        sb.append("\n现场照片：");
        if (StringUtil.isNotBlank(multipleVisitDTO.getImgSrc())) {
            String[] imgs = multipleVisitDTO.getImgSrc().split(",");
            for (String img : imgs) {
                sb.append(String.format("{{[img:%s]}}", img));
            }
        }

        return sb.toString();
    }

    /**
     * 工程师再次出发
     *
     * @param dbOrderWork 数据库工单
     * @param omsOperator 操作对象
     */
    String againSetOut(OrderWork dbOrderWork, OmsOperator omsOperator) {
        StringBuilder sb = new StringBuilder();
        OrderMultipleVisitDTO multipleVisitDTO = (OrderMultipleVisitDTO) omsOperator;

        sb.append("工程师再次出发（").append(multipleVisitDTO.getLongitude()).append(",")
                .append(multipleVisitDTO.getLatitude()).append("）");

        return sb.toString();
    }

    /**
     * 工程师再次上门
     *
     * @param dbOrderWork 数据库工单
     * @param omsOperator 操作对象
     */
    String againVisit(OrderWork dbOrderWork, OmsOperator omsOperator) {
        StringBuilder sb = new StringBuilder();

        Double distance = null;
        do {
            if (omsOperator.getLongitude() == null || omsOperator.getLatitude() == null) {
                break;
            }

            OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(dbOrderWork.getOrderId());
            if (orderDetail.getLongitude() == null || orderDetail.getLatitude() == null) {
                break;
            }

            distance = MathUtil.GetDistance(orderDetail.getLongitude(), orderDetail.getLatitude(), omsOperator.getLongitude(), omsOperator.getLatitude());
        } while (false);

        // 记录上门距离
        sb.append("上门距离：");

        String distanceLog;
        if (distance == null) {
            distanceLog = "位置离线，";
        } else {
            distanceLog = String.format("%.2f KM，", distance / 1000);
        }

        sb.append(distanceLog);
        sb.append("上门时间：");
        sb.append(DateUtil.getNowFormatted());

        return sb.toString();
    }

    /**
     * 取消再次上门
     *
     * @param dbOrderWork 数据库工单
     * @param omsOperator 操作对象
     */
    String cancelAgainVisit(OrderWork dbOrderWork, OmsOperator omsOperator) {
        StringBuilder sb = new StringBuilder();
        OrderMultipleVisitDTO multipleVisitDTO = (OrderMultipleVisitDTO) omsOperator;

        if (Objects.equals(multipleVisitDTO.getOperatorType(), GlobalConsts.OPERATE_USER_TYPE_MASTER)) {
            sb.append("工程师取消收款");
        } else {
            sb.append("取消缘由：");
            if (CollectionUtil.isNotNullOrEmpty(multipleVisitDTO.getReasonValueList())) {
                multipleVisitDTO.getReasonValueList().forEach(e -> {
                    sb.append(e).append(";");
                });
            } else {
                sb.append("用户取消服务");
            }
        }

        return sb.toString();
    }

    /**
     * 取消再次上门
     *
     * @param dbOrderWork 数据库工单
     * @param omsOperator 操作对象
     */
    String cancelOrderPay(OrderWork dbOrderWork, OmsOperator omsOperator) {
        StringBuilder sb = new StringBuilder();
        CancelPayDTO cancelPayDTO = (CancelPayDTO) omsOperator;

        if (NumberUtil.isNotNullOrZero(cancelPayDTO.getAmountType())) {
            sb.append("金额类型：");
            if (Objects.equals(cancelPayDTO.getAmountType(), OrderPayConsts.ORDER_PAY_DEPOSIT)) {
                sb.append("定金\n");
            } else if (Objects.equals(cancelPayDTO.getAmountType(), OrderPayConsts.ORDER_PAY_PROGRESS)) {
                sb.append("进度款\n");
            }
        }
        sb.append("取消原因：用户取消服务");

        return sb.toString();
    }


    /**
     * 工程师改价格
     *
     * @param omsOperator 操作对象
     */
    String masterChangePrice(OmsOperator omsOperator) {
        ChangePriceDTO changePriceDTO = (ChangePriceDTO) omsOperator;

        Integer onlyVisit = changePriceDTO.getOnlyVisit();
        String priceStr = this.amount2String(changePriceDTO.getPrice());
        if (Objects.equals(onlyVisit, GlobalConsts.YES)) {
            return priceStr + "; 上门费";
        }

        return priceStr;
    }

    /**
     * 填保单号
     *
     * @param omsOperator 操作对象
     */
    String manualCode(OmsOperator omsOperator) {
        ManualCodeDTO manualCodeDTO = (ManualCodeDTO) omsOperator;
        return manualCodeDTO.getManualCode();
    }

    /**
     * 工程师备注
     *
     * @param omsOperator 操作对象
     */
    String masterRemark(OmsOperator omsOperator) {
        MasterRemarkDTO masterRemarkDTO = (MasterRemarkDTO) omsOperator;
        return masterRemarkDTO.getRemark();
    }

    /**
     * 工程师发票
     *
     * @param omsOperator 操作对象
     */
    String masterInvoiceInfo(OmsOperator omsOperator) {
        MasterRemarkDTO masterRemarkDTO = (MasterRemarkDTO) omsOperator;
        return masterRemarkDTO.getInvoiceInfo();
    }

    /**
     * 工程师发票照片
     *
     * @param omsOperator 操作对象
     */
    String masterInvoicePic(OmsOperator omsOperator) {
        MasterRemarkDTO masterRemarkDTO = (MasterRemarkDTO) omsOperator;
        if (StringUtil.isBlank(masterRemarkDTO.getInvoiceUrl())) {
            return "";
        }

        String[] imgArray = masterRemarkDTO.getInvoiceUrl().split(",");
        StringBuilder log = new StringBuilder();
        log.append("发票照片:");
        for (String str : imgArray) {
            log.append(String.format("{{[img:%s]}}", str));
        }

        return log.toString();
    }

    /**
     * 工单照片
     *
     * @param omsOperator 操作对象
     */
    String orderImage(OmsOperator omsOperator) {
        OrderImageDTO orderImageDTO = (OrderImageDTO) omsOperator;

        if (orderImageDTO.getOpType() == OrderConsts.ORDER_IMAGE_DELETE) {
            return String.format("删除图片%d", orderImageDTO.getIndex());
        }
        return String.format("{{[img:%s]}}", orderImageDTO.getUrl());
    }

    /**
     * 附件照片
     *
     * @param omsOperator 操作对象
     */
    String orderAttachmentImage(OmsOperator omsOperator) {
        ModifyOrderAttachmentDTO orderImageDTO = (ModifyOrderAttachmentDTO) omsOperator;

        // 若是 更新操作 且 没有照片路径 就不记录日志。
        if (Objects.equals(orderImageDTO.getOpType(), OrderConsts.ORDER_IMAGE_UPDATE) && StringUtils.isBlank(orderImageDTO.getSrc())) {
            logger.error("订单号：[{}]，照片src不能为空！！");
            return "";
        }

        StringBuilder log = new StringBuilder();

        // 附件名称、附件分类名称
        String attachmentName = "";
        String attachmentTypeName = "";

        // 获取指定的【附件分类】信息
        ConfOrderAttachmentCategory attachmentCategory = confOrderAttachmentCategoryService.findCategoryById(orderImageDTO.getType());
        if (Objects.nonNull(attachmentCategory)) {
            attachmentName = attachmentCategory.getCategName();
            if (OrderAttachmentCategoryTypeEnum.cache.containsKey(attachmentCategory.getType())) {
                attachmentTypeName = OrderAttachmentCategoryTypeEnum.cache.get(attachmentCategory.getType()).getName();
            }
        }

        // 删除
        if (orderImageDTO.getOpType() == OrderConsts.ORDER_IMAGE_DELETE) {
            log.append(String.format("删除%s", attachmentName));
            return log.toString();
        }

        // 如果是视频，则获取视频的“某一帧”作为图片，放到工单日志中
        if (OrderAttachmentConsts.isVideoType(orderImageDTO.getType())) {
            log.append(String.format("{{[img:%s?x-oss-process=video/snapshot,t_10000,m_fast]}}", orderImageDTO.getSrc()));
        } else {
            log.append(String.format("{{[img:%s]}}", orderImageDTO.getSrc()));
        }

        log.append("\n");
        log.append(String.format("上传%s：%s", attachmentTypeName, attachmentName));
        return log.toString();
    }

    /**
     * 修改工单照片
     *
     * @param omsOperator 操作对象
     */
    String editOrderImage(OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();
        OrderPhotoDTO orderPhotoDTO = (OrderPhotoDTO) omsOperator;
        Integer appliqueStatus = orderPhotoDTO.getAppliqueStatus();
        Integer masterImageStatus = orderPhotoDTO.getMasterImageStatus();


        if (orderPhotoDTO.getAppliqueStatus() != null) {
            log.append("贴花照片:");
            if (Objects.equals(appliqueStatus, GlobalConsts.YES)) {
                log.append("有效");
            } else {
                log.append("无效");
            }
            log.append("\n");
        }

        if (orderPhotoDTO.getMasterImageStatus() != null) {
            log.append("个人形象:");
            if (Objects.equals(masterImageStatus, GlobalConsts.YES)) {
                log.append("合格");
            } else {
                log.append("不合格");
            }
            log.append("\n");
        }

        Map<Long, List<OrderAttachment>> oldAttachmentMap = orderPhotoDTO.getOldAttachmentList().stream()
                .collect(Collectors.groupingBy(OrderAttachment::getAttachmentId));
        if (CollectionUtil.isNotNullOrEmpty(orderPhotoDTO.getAttachmentList())) {
            orderPhotoDTO.getAttachmentList().stream().forEach(newAttachment -> {

                List<OrderAttachment> oldAttachmentList = oldAttachmentMap.get(newAttachment.getAttachmentId());
                if (CollectionUtils.isEmpty(oldAttachmentList)) {
                    return;
                }
                OrderAttachment oldAttachment = oldAttachmentList.get(0);
                // 如果页面的审核状态没有改过，就到循环到下一条
                if (Objects.equals(oldAttachment.getReviewStatus(), newAttachment.getReviewStatus())) {
                    return;
                }

                String name = OrderAttachmentTypeEnum.getName(oldAttachment.getType());
                if (StringUtils.isBlank(name)) {
                    return;
                }
                log.append(name);
                if (name.endsWith("照片") || name.endsWith("照")) {
                    log.append("：");
                } else {
                    log.append("照片：");
                }

                log.append("人工审核");
                log.append(OrderConsts.getImageReviewStatusName(newAttachment.getReviewStatus()));
                log.append("\n");
            });
        }

        if (orderPhotoDTO.getIsAdd() != null && orderPhotoDTO.getIsAdd()) {
            String[] addArr = orderPhotoDTO.getAddUrl().split(",");
            log.append("新增图片:");
            for (String str : addArr) {
                log.append(String.format("{{[img:%s]}}", str));
            }
        }

        if (orderPhotoDTO.getIsDelete() != null && orderPhotoDTO.getIsDelete()) {
            String[] delArr = orderPhotoDTO.getDeleteUrl().split(",");
            log.append("删除图片:");
            for (String str : delArr) {
                log.append(String.format("{{[img:%s]}}", str));
            }
        }

        log.append("备注：");
        log.append(orderPhotoDTO.getOperatorRemark());
        return log.toString();
    }

    /**
     * 贴花照片
     *
     * @param omsOperator 操作对象
     */
    String appliqueImage(OmsOperator omsOperator) {
        OrderImageDTO orderImageDTO = (OrderImageDTO) omsOperator;

        StringBuilder sb = new StringBuilder();

        if (orderImageDTO.getOpType() == OrderConsts.ORDER_IMAGE_DELETE) {
            sb.append(String.format("删除图片%d", orderImageDTO.getIndex()));
        } else {
            sb.append(String.format("{{[img:%s]}}", orderImageDTO.getUrl()));
        }
        return sb.toString();
    }

    /**
     * 工单工程师照片
     *
     * @param omsOperator 操作对象
     */
    String masterImage(OmsOperator omsOperator) {
        OrderImageDTO orderImageDTO = (OrderImageDTO) omsOperator;

        StringBuilder sb = new StringBuilder();

        if (orderImageDTO.getOpType() == OrderConsts.ORDER_IMAGE_DELETE) {
            sb.append(String.format("删除图片%d", orderImageDTO.getIndex()));
        } else {
            sb.append(String.format("{{[img:%s]}}", orderImageDTO.getUrl()));
        }
        return sb.toString();
    }

    /**
     * 工单工程师照片
     *
     * @param omsOperator 操作对象
     */
    String photoDetection(OmsOperator omsOperator) {
        OrderPhotoDetectionDTO dto = (OrderPhotoDetectionDTO) omsOperator;

        StringBuilder sb = new StringBuilder();
        sb.append("照片类型：").append(dto.getPictureTypeName()).append("\n");
        sb.append("审核结果：");
        sb.append(OrderConsts.getImageReviewStatusName(dto.getAiAuditStatus()));
        return sb.toString();
    }

    /**
     * 支付日志
     *
     * @param omsOperator 操作对象
     */
    String payLog(OrderWork orderWork, OmsOperator omsOperator) {
        OrderPayResultDRO orderPayResultDRO = (OrderPayResultDRO) omsOperator;

        StringBuilder logRemark = new StringBuilder();
        logRemark.append(OrderPayConsts.getAmountTypeName(orderPayResultDRO.getAmountType()));
        if (Objects.equals(orderPayResultDRO.getDuplicateType(), OrderPayConsts.ORDER_PAY_DUPLICATION_TYPE_SYS)) {
            logRemark.append("[系统重复]");
        } else if (Objects.equals(orderPayResultDRO.getDuplicateType(), OrderPayConsts.ORDER_PAY_DUPLICATION_TYPE_BIZ)) {
            logRemark.append("[重复支付]");
        } else {
            logRemark.append("，未支付->").append(PayConsts.getPayStatusName(orderPayResultDRO.getPayStatus()));
        }
        // if (!NumberUtil.isNullOrZero(payResultDTO.getDiscountAmount())) {
        //     logRemark.append("，用户实际支付：").append(this.amount2String(orderPayResultDRO.getAmount()));
        //     logRemark.append("，优惠：").append(this.amount2String(orderPayResultDRO.getDiscountAmount()));
        // } else {
        //     logRemark.append("，非现金：").append(this.amount2String(payResultDTO.getAmount()));
        // }
        logRemark.append("，非现金：").append(this.amount2String(orderPayResultDRO.getAmount()));

        if (Objects.equals(orderPayResultDRO.getAgentType(), GlobalConsts.YES)) {
            logRemark.append("，好友代付");
        }
        logRemark.append("，支付渠道：").append(PayConsts.getPayChannelName(orderPayResultDRO.getPayChannelId()));
        if (Objects.equals(PayConsts.PAY_CHANNEL_PLATFORM_BANKTRANSFER, orderPayResultDRO.getPayChannelId())) {
            logRemark.append("，转账账户：").append(orderPayResultDRO.getPayerThirdAccount());
            logRemark.append("，银行名称：").append(orderPayResultDRO.getPayerThirdAccountBank());
            logRemark.append("，公司账户：").append(orderPayResultDRO.getPayeeThirdAccountName());
        }

        if (NumberUtil.isNotNullOrZero(orderPayResultDRO.getPayTargetChannelId())) {
            logRemark.append("-").append(PayConsts.getPayChannelName(orderPayResultDRO.getPayTargetChannelId()));
        }

        logRemark.append("，支付方式：").append(PayConsts.getPayTypeName(orderPayResultDRO.getPayType()));
        logRemark.append("，流水号：").append(orderPayResultDRO.getPayOutTradeNo());
        logRemark.append("，支付角色：")
                .append(Objects.equals(orderPayResultDRO.getPayType(), GlobalConsts.PAY_TYPE_APP) ? "工程师" : "用户");
        if (Objects.equals(orderPayResultDRO.getTradeType(), PayConsts.PAY_TRADE_TYPE_REFUND)) {
            logRemark.append("，角色id：").append(StringUtils.defaultString(orderPayResultDRO.getPayeeThirdAccount()));
        } else {
            logRemark.append("，角色id：").append(StringUtils.defaultString(orderPayResultDRO.getPayerThirdAccount()));
        }
        logRemark.append("，支付时间：").append(orderPayResultDRO.getPayTime() != null ?
                (DateUtil.toString(orderPayResultDRO.getPayTime(), DateUtil.FORMAT_DATE)) :
                "");

        if (Objects.equals(orderPayResultDRO.getPayChannelId(), GlobalConsts.PAY_CHANNEL_PLATFORM_BANKTRANSFER)) {
            if (StringUtil.isNotBlank(orderPayResultDRO.getImageUrls())) {
                String[] imgs = orderPayResultDRO.getImageUrls().split(",");
                logRemark.append("汇款凭证：");
                for (int i = 0; i < imgs.length; i++) {
                    logRemark.append(String.format("{{[img:%s]}} ", imgs[i]));
                }
            }
        }

        // 代付
        logRemark.append("，代付：").append(Objects.equals(orderPayResultDRO.getAgentType(), GlobalConsts.YES) ? "是" : "否");

        try {
            if (omsOperator.getLongitude() != null && omsOperator.getLatitude() != null) {
                OrderDetail detail = orderDetailService.findOrderDetailByKey(omsOperator.getWorkId());
                if (detail != null && detail.getLatitude() != null && detail.getLongitude() != null) {
                    // 支付距离 ：上门扫码时的位置>上传形象照的位置>用户下单的地址
                    Integer distance = orderPositionBService.customerMinPayDistance(orderWork.getWorkId(),
                            orderWork.getVisitUserId(), omsOperator.getLongitude(), omsOperator.getLatitude());
                    if (distance != null) {
                        logRemark.append("\n支付距离：").append(MathUtil.div(distance, 1000, 2)).append("km");
                    }
                }
            }
        } catch (Exception e) {
            logger.error("支付距离日志写入失败" + e.getMessage(), e);
        }


        return logRemark.toString();
    }

    /**
     * 完成
     *
     * @param omsOperator 操作对象
     */
    String complete(OrderWork dbOrderWork, OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();

        if (StringUtils.isNotBlank(omsOperator.getOperatorLogRemark()) &&
                !Objects.equals("null", omsOperator.getOperatorLogRemark())) {
            log.append(omsOperator.getOperatorLogRemark());
        }

        return log.toString();
    }

    /**
     * 服务完成
     *
     * @param omsOperator 操作对象
     */
    String serviceComplete(OrderWork dbOrderWork, OmsOperator omsOperator) {
        return "工单服务完成";
    }

    /**
     * 服务完成审核
     *
     * @param omsOperator 操作对象
     */
    String serviceCompleteReview(OrderWork dbOrderWork, OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();

        OrderCompleteReviewDTO orderCompleteReviewDTO = (OrderCompleteReviewDTO) omsOperator;
        Integer autoReview = orderCompleteReviewDTO.getAutoReview();
        Integer serviceCompleteReviewStatus = orderCompleteReviewDTO.getServiceCompleteReviewStatus();
        if (Objects.equals(autoReview, GlobalConsts.YES)) {
            log.append("自动审核：");
            log.append(Objects.equals(serviceCompleteReviewStatus, OrderConsts.REVIEW_STATUS_SUCCESS) ? "成功" : "失败");
        } else {
            List<ServiceItemVO> itemVOS = orderCompleteReviewDTO.getServiceItemVOList();
            if (CollectionUtil.isNotNullOrEmpty(itemVOS)) {
                itemVOS.forEach(item -> {
                    log.append(item.getServItemName())
                            .append("：")
                            .append(MoneyUtil.parseToYuanStr(item.getOldInternalSettlementPrice()))
                            .append("-")
                            .append(MoneyUtil.parseToYuanStr(item.getInternalSettlementPrice()))
                            .append("\n");
                });
            }

            log.append("服务审核结果：");
            log.append(Objects.equals(serviceCompleteReviewStatus, OrderConsts.REVIEW_STATUS_SUCCESS) ? "成功" : "失败");
            log.append("\n");
            if (Objects.equals(serviceCompleteReviewStatus, OrderConsts.REVIEW_STATUS_FAIL)) {
                log.append("失败缘由：");
                orderCompleteReviewDTO.getAuditReason().forEach(e -> {
                    log.append(e.getText());
                    log.append(",");
                });
            }
            if (Objects.nonNull(orderCompleteReviewDTO.getContent())) {
                log.append(";审核备注：");
                log.append(orderCompleteReviewDTO.getContent());
            }
        }
        return log.toString();
    }

    /**
     * 工程师联系用户
     *
     * @param omsOperator 操作对象
     */
    String contactUser(OmsOperator omsOperator, OrderLog orderLog) {
        ContactUserDTO contactUserDTO = (ContactUserDTO) omsOperator;
        orderLog.setCreateTime(contactUserDTO.getCallTime());
        return contactUserDTO.getCallDesc();
    }

    /**
     * 分转为元字符串
     */
    String amount2String(Integer amount) {
        if (amount == null) {
            return null;
        }

        double dAmount = AmountUtil.fen2Yuan(amount).doubleValue();
        return String.format("%.2f", dAmount);
    }

    /**
     * 分转为元字符串，null作为0处理
     */
    String amount2StringNullAs0(Integer amount) {
        if (amount == null) {
            return "0";
        }

        double dAmount = AmountUtil.fen2Yuan(amount).doubleValue();
        return String.format("%.2f", dAmount);
    }

    /**
     * 订单是否等待支付
     *
     * @param orderWork
     * @return
     */
    private boolean isWaitPrePay(OrderWork orderWork) {
        return orderWorkBService.isWaitPrePay(orderWork);
    }

    /**
     * 工程师改预约时间
     *
     * @param omsOperator 操作对象
     */
    String masterModifyDutyTime(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ModifyDutyTimeDTO modifyDutyTimeDTO = (ModifyDutyTimeDTO) omsOperator;

        List<String> logList = Lists.newArrayList();

        if (dbOrderWork.getDutyTime() == null && modifyDutyTimeDTO.getDutyTime() != null) {
            logList.add(String.format("预约时间：->%s",
                    DateUtil.toString(modifyDutyTimeDTO.getDutyTime(), DateUtil.FORMAT_DATETIME)));
        } else if (dbOrderWork.getDutyTime() != null && modifyDutyTimeDTO.getDutyTime() == null) {
            logList.add(String.format("预约时间：%s-> ",
                    DateUtil.toString(dbOrderWork.getDutyTime(), DateUtil.FORMAT_DATETIME)));
        } else {
            String dbDutyTime = DateUtil.toString(dbOrderWork.getDutyTime(), DateUtil.FORMAT_DATETIME);
            String dutyTime = DateUtil.toString(modifyDutyTimeDTO.getDutyTime(), DateUtil.FORMAT_DATETIME);
            logList.add(String.format("预约时间：%s->%s", dbDutyTime, dutyTime));
        }

        // 预约失败
        if (Objects.equals(OrderDutyConsts.DUTY_STATUS_FAIL, modifyDutyTimeDTO.getDutyStatus())) {
            //从无到有
            if ((dbOrderWork.getNextContactTime() == null && modifyDutyTimeDTO.getNextContactTime() != null) ||
                    !Objects.equals(dbOrderWork.getDutyStatus(), modifyDutyTimeDTO.getDutyStatus())) {
                logList.add(String.format("预约失败：->下次联系时间：%s，失败原因：%s",
                        DateUtil.toString(modifyDutyTimeDTO.getNextContactTime(), DateUtil.FORMAT_DATETIME),
                        OrderDutyConsts.getDutyFailedReasonName(modifyDutyTimeDTO.getDutyFailCode())));
            }
            //从有到有
            else if (dbOrderWork.getNextContactTime() != null && modifyDutyTimeDTO.getNextContactTime() != null) {
                logList.add(String.format("预约失败：->下次联系时间：%s->%s，失败原因：%s",
                        DateUtil.toString(dbOrderWork.getNextContactTime(), DateUtil.FORMAT_DATETIME),
                        DateUtil.toString(modifyDutyTimeDTO.getNextContactTime(), DateUtil.FORMAT_DATETIME),
                        OrderDutyConsts.getDutyFailedReasonName(modifyDutyTimeDTO.getDutyFailCode())));
            }
        }

        // 预约备注
        if (StringUtils.isNotBlank(modifyDutyTimeDTO.getRemark())) {
            logList.add(String.format("备注：%s", modifyDutyTimeDTO.getRemark()));
        }

        boolean isWhiteMaster = orderStockBService.isWhiteMasterId(modifyDutyTimeDTO.getMasterId());
        logList.add(String.format("库存试点工程师：%s", isWhiteMaster ? "是" : "否"));

        boolean isWhiteCity = orderStockBService.isWhiteWorkCity(dbOrderWork.getCityId());
        logList.add(String.format("库存试点城市：%s", isWhiteCity ? "是" : "否"));

        // 提过有效联系，记录日志
        if (Objects.equals(modifyDutyTimeDTO.getSkipContact(), GlobalConsts.YES)) {
            logList.add("工程师跳过联系用户确认时间");
        }

        return StringUtils.join(logList, '\n');
    }

    /**
     * 签到
     *
     * @param omsOperator 操作对象
     */
    String signIn(OrderWork dbOrderWork, OmsOperator omsOperator) {
        OrderTmallExtendDTO orderTmallExtendDTO = (OrderTmallExtendDTO) omsOperator;

        StringBuilder sb = new StringBuilder();
        if (Objects.equals(GlobalConsts.YES, orderTmallExtendDTO.getSignInStatus())) {
            sb.append("签到成功");
        } else {
            sb.append("签到失败");
            if (StringUtil.isNotBlank(orderTmallExtendDTO.getSignInFailReasonName())) {
                sb.append(",失败原因：").append(orderTmallExtendDTO.getSignInFailReasonName());
            }
        }
        return sb.toString();
    }

    /**
     * 核销
     *
     * @param omsOperator 操作对象
     */
    String verification(OrderWork dbOrderWork, OmsOperator omsOperator) {
        OrderTmallExtendDTO orderTmallExtendDTO = (OrderTmallExtendDTO) omsOperator;

        StringBuilder sb = new StringBuilder();
        if (Objects.equals(GlobalConsts.YES, orderTmallExtendDTO.getVerification())) {
            sb.append("核销成功");
        } else {
            sb.append("核销失败");
        }

        return sb.toString();
    }


    /**
     * 挂起
     *
     * @param omsOperator 操作对象
     */
    String orderWorkSuspend(OrderWork dbOrderWork, OmsOperator omsOperator) {
        OrderWorkSuspendDTO orderWorkSuspendDTO = (OrderWorkSuspendDTO) omsOperator;
        // 添加挂起备注
        String reasonDesc = orderWorkSuspendDTO.getReasonDesc();
        // 添加挂起原因
        StringBuilder sb = new StringBuilder();
        sb.append("挂起原因：");
        if (Objects.nonNull(orderWorkSuspendDTO.getDutyFailCode())) {
            sb.append(OrderDutyConsts.getDutySuspendReasonName(orderWorkSuspendDTO.getDutyFailCode())).append("，");
        }
        if (StringUtils.isNotBlank(reasonDesc)) {
            sb.append(reasonDesc).append("，");
        }
        sb.append("下次联系时间：").append(DateUtil.toString(orderWorkSuspendDTO.getNextContactTime()));
        return sb.toString();
    }

    /**
     * 添加企业微信日志
     *
     * @param omsOperator
     * @return
     */
    private String enterpriseWeChatLog(OmsOperator omsOperator) {
        EnterpriseWeChatLog weChatLog = (EnterpriseWeChatLog) omsOperator;

        // 企业微信日志
        StringBuilder sb = new StringBuilder();
        sb.append("添加企业微信用户微信昵称：");
        sb.append(weChatLog.getNickname());
        sb.append("\n");
        sb.append("添加时间：");
        sb.append(DateUtil.toString(weChatLog.getAddTime()));
        return sb.toString();
    }

    /**
     * 修改难度系数
     *
     * @param omsOperator
     * @return
     */
    private String modifyDifficultRatio(OmsOperator omsOperator) {
        OrderExtendDTO orderExtendDTO = (OrderExtendDTO) omsOperator;

        // 企业微信日志
        StringBuilder sb = new StringBuilder();
        if (NumberUtil.isNullOrZero(orderExtendDTO.getDifficultRatioId())) {
            sb.append("未选择");
        } else {
            sb.append("选择难度系数：").append(orderExtendDTO.getDifficultRatio().toString());
        }
        return sb.toString();
    }

    /**
     * 退款申请
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    private String applyRefund(OrderWork dbOrderWork, OmsOperator omsOperator) {
        RefundApplyDTO refundApplyDTO = (RefundApplyDTO) omsOperator;
        // 申请金额-所支付的金额
        Integer applyAmount = 0;
        if (Objects.equals(dbOrderWork.getPrepayStatus(), PayConsts.PAY_STATUS_DONE)
                && dbOrderWork.getPrepayAmount() != null) {
            applyAmount = applyAmount + dbOrderWork.getPrepayAmount();
        }
        if (Objects.equals(dbOrderWork.getDepositStatus(), PayConsts.PAY_STATUS_DONE)
                && dbOrderWork.getDepositAmount() != null) {
            applyAmount = applyAmount + dbOrderWork.getDepositAmount();
        }

        StringBuilder sb = new StringBuilder();
        sb.append("用户申请退款：");
        sb.append(MoneyUtil.parseToYuanStr(applyAmount));
        sb.append("\n");
        if (refundApplyDTO.getReasonMap() != null) {
            sb.append("退款原因：");
            refundApplyDTO.getReasonMap().forEach((k, v) -> {
                sb.append(v);
            });
        }
        return sb.toString();
    }

    private String refundUpdate(OrderWork dbOrderWork, OmsOperator omsOperator) {
        RefundDTO refundDTO = (RefundDTO) omsOperator;
        StringBuilder sb = new StringBuilder();
        sb.append("原有退款信息：").append("\n");
        if (Objects.nonNull(refundDTO.getHistoryRefundReview()) && Objects.equals(refundDTO.getHistoryRefundReview().getReviewStatus(), OrderConsts.OMS_ORDER_REVIEW_STATUS_CHECK)) {
            RefundDTO refundInfo = JSON.parseObject(refundDTO.getHistoryRefundReview().getReviewData(), RefundDTO.class);
            sb.append("退款方式 / 路径：");

            if (Objects.equals(refundInfo.getRefundType(), RefundTypeEnum.ORIGINAL_REFUND.getType())) {
                sb.append(OrderConsts.getRefundTypeName(refundInfo.getRefundType())).append(" / ").append("--");
            } else {
                sb.append(OrderConsts.getRefundTypeName(refundInfo.getRefundType())).append(" / ").append(PayConsts.getPayChannelName(refundInfo.getPayTargetChannelId()));
            }
            sb.append("\n");
            if (!Objects.equals(refundInfo.getRefundType(), RefundTypeEnum.ORIGINAL_REFUND.getType())
                    && !Objects.equals(refundInfo.getPayTargetChannelId(), RefundTypeEnum.CASH_REFUND.getType())) {
                sb.append("退款账户：");
                switch (refundInfo.getPayTargetChannelId()) {
                    case PayConsts.PAY_CHANNEL_PLATFORM_WEIXINPAY:
                    case PayConsts.PAY_CHANNEL_PLATFORM_ALIPAY:
                        sb.append(refundInfo.getPayeeThirdAccount()).append("/").append(refundInfo.getPayeeThirdAccountName());
                        break;
                    case PayConsts.PAY_CHANNEL_PLATFORM_BANKTRANSFER:
                        sb.append(refundInfo.getPayeeThirdAccountBank()).append("/").append(refundInfo.getPayeeThirdAccount()).append("/").append(refundInfo.getPayeeThirdAccountName());
                        break;
                }
                sb.append("\n");
            }
            sb.append("退款金额：" + MoneyUtil.parseToYuan(refundInfo.getRefundAmount()));
            sb.append("\n");
            sb.append("退款缘由：");
            List<String> reasonNameList = refundInfo.getReasonList()
                    .stream()
                    .map(KVDict::getText)
                    .collect(Collectors.toList());
            sb.append(String.format("%s；%s", StringUtils.join(Optional.ofNullable(reasonNameList).orElse(Lists.newArrayList()), "；"), StringUtils.defaultString(refundDTO.getContent())));
            sb.append("\n");
        } else if (Objects.nonNull(refundDTO.getHistoryOrderPay())) {
            OrderPay historyOrderPay = refundDTO.getHistoryOrderPay();
            sb.append("退款方式 / 路径：");

            if (Objects.equals(historyOrderPay.getRefundType(), RefundTypeEnum.ORIGINAL_REFUND.getType())) {
                sb.append(OrderConsts.getRefundTypeName(historyOrderPay.getRefundType())).append(" / ").append("--");
            } else {
                sb.append(OrderConsts.getRefundTypeName(historyOrderPay.getRefundType())).append(" / ").append(PayConsts.getPayChannelName(historyOrderPay.getPayTargetChannelId()));
            }
            sb.append("\n");
            if (!Objects.equals(historyOrderPay.getRefundType(), RefundTypeEnum.ORIGINAL_REFUND.getType())
                    && !Objects.equals(historyOrderPay.getPayTargetChannelId(), RefundTypeEnum.CASH_REFUND.getType())) {
                sb.append("退款账户：");
                switch (historyOrderPay.getPayTargetChannelId()) {
                    case PayConsts.PAY_CHANNEL_PLATFORM_WEIXINPAY:
                    case PayConsts.PAY_CHANNEL_PLATFORM_ALIPAY:
                        sb.append(historyOrderPay.getPayeeThirdAccount()).append("/").append(historyOrderPay.getPayeeThirdAccountName());
                        break;
                    case PayConsts.PAY_CHANNEL_PLATFORM_BANKTRANSFER:
                        sb.append(historyOrderPay.getPayeeThirdAccountBank()).append("/").append(historyOrderPay.getPayeeThirdAccount()).append("/").append(historyOrderPay.getPayeeThirdAccountName());
                        break;
                }
                sb.append("\n");
            }
            sb.append("退款金额：" + MoneyUtil.parseToYuan(historyOrderPay.getAmount()));
            sb.append("\n");
            sb.append("退款缘由：");
            List<String> reasonNameList = refundDTO.getHistoryRemark()
                    .getDetailVOList()
                    .stream()
                    .map(OrderRemarkDetailVO::getMapName)
                    .collect(Collectors.toList());
            sb.append(String.format("%s；%s", StringUtils.join(Optional.ofNullable(reasonNameList).orElse(Lists.newArrayList()), "；"), StringUtils.defaultString(refundDTO.getHistoryRemark().getContent())));
            sb.append("\n");
        }

        sb.append("现有退款信息：").append("\n");
        sb.append("退款方式 / 路径：");

        if (Objects.equals(refundDTO.getRefundType(), RefundTypeEnum.ORIGINAL_REFUND.getType())) {
            sb.append(OrderConsts.getRefundTypeName(refundDTO.getRefundType())).append(" / ").append("--");
        } else {
            sb.append(OrderConsts.getRefundTypeName(refundDTO.getRefundType())).append(" / ").append(PayConsts.getPayChannelName(refundDTO.getPayTargetChannelId()));
        }
        sb.append("\n");
        if (!Objects.equals(refundDTO.getRefundType(), RefundTypeEnum.ORIGINAL_REFUND.getType())
                && !Objects.equals(refundDTO.getPayTargetChannelId(), RefundTypeEnum.CASH_REFUND.getType())) {
            sb.append("退款账户：");
            switch (refundDTO.getPayTargetChannelId()) {
                case PayConsts.PAY_CHANNEL_PLATFORM_WEIXINPAY:
                case PayConsts.PAY_CHANNEL_PLATFORM_ALIPAY:
                    sb.append(refundDTO.getPayeeThirdAccount()).append("/").append(refundDTO.getPayeeThirdAccountName());
                    break;
                case PayConsts.PAY_CHANNEL_PLATFORM_BANKTRANSFER:
                    sb.append(refundDTO.getPayeeThirdAccountBank()).append("/").append(refundDTO.getPayeeThirdAccount()).append("/").append(refundDTO.getPayeeThirdAccountName());
                    break;
            }
            sb.append("\n");
        }
        sb.append("退款金额：" + MoneyUtil.parseToYuan(refundDTO.getRefundAmount()));
        sb.append("\n");
        sb.append("退款缘由：");
        List<String> reasonNameList = refundDTO.getReasonList()
                .stream()
                .map(KVDict::getText)
                .collect(Collectors.toList());
        sb.append(String.format("%s；%s", StringUtils.join(Optional.ofNullable(reasonNameList).orElse(Lists.newArrayList()), "；"), StringUtils.defaultString(refundDTO.getContent())));
        sb.append("\n");
        return sb.toString();
    }

    /**
     * 退款单
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    private String refund(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ZsNormalRefundWorkDTO refundDTO = (ZsNormalRefundWorkDTO) omsOperator;
        RefundDTO newRefundDTO = refundDTO.getRefundDTO();

        // 退款日志
        StringBuilder sb = new StringBuilder();
        sb.append("退款服务商：" + refundDTO.getManageCompanyName());
        sb.append("\n");

        if (StringUtils.isNotBlank(refundDTO.getMasterName())) {
            String[] split = refundDTO.getMasterName().split("-");
            sb.append("退款工程师：" + split[0]);
            sb.append("\n");
        }


        sb.append("退款金额：￥")
                .append(MoneyUtil.parseToYuan(newRefundDTO.getOrderRefundAmount()))
                .append("\n");

        if (NumberUtil.isNotNullOrZero(newRefundDTO.getDiscountRefundAmount())) {
            sb.append("应退款金额：￥")
                    .append(MoneyUtil.parseToYuan(Optional.ofNullable(newRefundDTO.getRefundAmount()).orElse(0)));
            sb.append("（增值产品已承担退款：￥")
                    .append(MoneyUtil.parseToYuan(Optional.ofNullable(newRefundDTO.getDiscountRefundAmount()).orElse(0))).append("）");
            sb.append("\n");
        }

        sb.append("退款方式 / 路径：");

        if (Objects.equals(refundDTO.getRefundType(), RefundTypeEnum.ORIGINAL_REFUND.getType())) {
            sb.append(OrderConsts.getRefundTypeName(refundDTO.getRefundType())).append(" / ").append("--");
        } else {
            sb.append(OrderConsts.getRefundTypeName(refundDTO.getRefundType())).append(" / ").append(PayConsts.getPayChannelName(refundDTO.getPayTargetChannelId()));
        }
        sb.append("\n");

        if (!Objects.equals(refundDTO.getRefundType(), RefundTypeEnum.ORIGINAL_REFUND.getType())
                && !Objects.equals(refundDTO.getPayTargetChannelId(), RefundTypeEnum.CASH_REFUND.getType())) {
            sb.append("退款账户：");
            switch (refundDTO.getPayTargetChannelId()) {
                case PayConsts.PAY_CHANNEL_PLATFORM_WEIXINPAY:
                case PayConsts.PAY_CHANNEL_PLATFORM_ALIPAY:
                    sb.append(refundDTO.getPayeeThirdAccount()).append("/").append(refundDTO.getPayeeThirdAccountName());
                    break;
                case PayConsts.PAY_CHANNEL_PLATFORM_BANKTRANSFER:
                    sb.append(refundDTO.getPayeeThirdAccountBank()).append("/").append(refundDTO.getPayeeThirdAccount()).append("/").append(refundDTO.getPayeeThirdAccountName());
                    break;
            }
            sb.append("\n");
        }

        OmsOrderReview orderRefundReview = orderReviewService.getOmsOrderReviewByOrderIdAndWorkIdAndType(refundDTO.getOrderId(), refundDTO.getWorkId(), OrderConsts.OMS_ORDER_REVIEW_REFUND);
        sb.append("退款状态：已录入");
        if (Objects.nonNull(orderRefundReview)) {
            sb.append("    待审核");
        }
        sb.append("\n");

        sb.append("退款缘由：");
        sb.append(String.format("%s；%s", StringUtils.join(Optional.ofNullable(refundDTO.getReasonNameList()).orElse(Lists.newArrayList()), "；"), StringUtils.defaultString(refundDTO.getOperatorRemark())));
        sb.append("\n");

        return sb.toString();
    }

    /**
     * 退款结果日志
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    private String refundResult(OrderWork dbOrderWork, OmsOperator omsOperator) {
        WorkRefundResultDTO refundDTO = (WorkRefundResultDTO) omsOperator;
        RefundResultDTO refundResultDTO = refundDTO.getRefundResultDTO();
        StringBuilder sb = new StringBuilder();
        if (Objects.nonNull(refundDTO.getAmountType()) && Objects.equals(refundDTO.getAmountType(), GlobalConsts.NONE)) {
            sb.append(OrderPayConsts.getAmountTypeName(refundDTO.getAmountType()));
        }
        sb.append("退款金额：" + MoneyUtil.parseToYuanStr(refundResultDTO.getRefundAmount()));
        sb.append("，退款结果：").append(PayConsts.getPayStatusName(refundResultDTO.getStatus()));
        if (Objects.nonNull(refundResultDTO.getChannelId()) && NumberUtil.isNullOrZero(dbOrderWork.getChannelPrepayAmount())) {
            sb.append("，退款渠道：").append(PayConsts.getPayChannelName(refundResultDTO.getChannelId()));
        }
        if (StringUtil.isNotBlank(refundResultDTO.getRefundNo())) {
            sb.append("，退款流水号：").append(StringUtils.defaultIfBlank(refundResultDTO.getRefundNo(), ""));
        }

        return sb.toString();
    }

    /**
     * 修改产品日志
     *
     * @param dbOrderWork
     * @param omsOperator
     * @return
     */
    private String modifyProduct(OrderWork dbOrderWork, OmsOperator omsOperator) {
        ModifyProductDTO modifyProductDTO = (ModifyProductDTO) omsOperator;
        StringBuilder sb = new StringBuilder();
        sb.append("产品修改:" + modifyProductDTO.getOldProductInfo() + "->" + modifyProductDTO.getNewProductInfo());
        return sb.toString();
    }

    /**
     * 订单修改记录保存
     *
     * @param orderWork
     * @param omsBaseOperator
     * @param logType
     * @auth xiewenbing
     */
    private void recordOrderChange(OrderWork orderWork, OmsBaseOperator omsBaseOperator, int logType) {
        if (Objects.isNull(orderWork) || Objects.isNull(omsBaseOperator)) {
            return;
        }

        switch (logType) {
            // 新单
            case OrderLogConsts.ORDER_LOG_TYPE_INPUT:
                if (Objects.nonNull(orderWork.getDutyTime())) {
                    recordOrderDutyTimeChange(orderWork.getDutyTime(), null, false, omsBaseOperator);
                }
                break;

            // 修改和确认
            case OrderLogConsts.ORDER_LOG_TYPE_CONFIRM:
            case OrderLogConsts.ORDER_LOG_TYPE_UPDATE:
                if (omsBaseOperator instanceof OrderDTO) {
                    OrderDTO orderDTO = (OrderDTO) omsBaseOperator;
                    if (Objects.isNull(orderDTO)) {
                        return;
                    }
                    OrderWork dbOrderWork = orderDTO.getDbOrderWork();
                    OrderWork newOrderWork = orderDTO.getOrderWork();

                    // 预约时间
                    if (!Objects.equals(dbOrderWork.getDutyTime(), newOrderWork.getDutyTime())) {
                        // 原来有预约时间才算改约
                        boolean updateOpCount = Objects.nonNull(dbOrderWork.getDutyTime()) && Objects.nonNull(newOrderWork.getDutyTime());
                        recordOrderDutyTimeChange(newOrderWork.getDutyTime(), dbOrderWork.getDutyTime(), updateOpCount, omsBaseOperator);
                    }
                }
                break;
            // 工程师app修改预约时间 和 天猫修改预约时间
            case OrderLogConsts.ORDER_LOG_TYPE_MODIFY_DUTY_TIME:
            case OrderLogConsts.ORDER_LOG_TYPE_MASTER_MODIFY_DUTY_TIME:
                if (omsBaseOperator instanceof ModifyDutyTimeDTO) {
                    ModifyDutyTimeDTO modifyDutyTimeDTO = (ModifyDutyTimeDTO) omsBaseOperator;
                    if (Objects.isNull(modifyDutyTimeDTO)) {
                        return;
                    }

                    this.recordOrderDutyTimeChange(modifyDutyTimeDTO.getDutyTime(), orderWork.getDutyTime(), true, omsBaseOperator);
                }
                break;
            // 派单
            case OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE:
                if (omsBaseOperator instanceof OrderDistributeDTO) {
                    OrderDistributeDTO distributeDTO = (OrderDistributeDTO) omsBaseOperator;
                    if (Objects.isNull(distributeDTO)) {
                        return;
                    }
                    this.recordOrderDistributeChange(distributeDTO.isAutoDistribute(), distributeDTO);
                }
                break;
            // 工程师照片
            case OrderLogConsts.ORDER_LOG_TYPE_MASTER_IMAGE:
                if (omsBaseOperator instanceof OrderImageDTO) {
                    OrderImageDTO orderImageDTO = (OrderImageDTO) omsBaseOperator;
                    if (Objects.isNull(orderImageDTO)) {
                        return;
                    }
                    this.recordOrderMasterImageChange(orderImageDTO);
                }
                break;
            // 上门扫码
            case OrderLogConsts.ORDER_LOG_TYPE_VISIT_QR:
                if (omsBaseOperator instanceof MasterVisitQrDTO) {
                    MasterVisitQrDTO masterVisitQrDTO = (MasterVisitQrDTO) omsBaseOperator;
                    if (Objects.isNull(masterVisitQrDTO)) {
                        return;
                    }

                    // 有微信openId则是扫码
                    String openId = masterVisitQrDTO.getOpenId();
                    if (StringUtil.isBlank(openId)) {
                        return;
                    }

                    this.recordOrderVisitScanChange(masterVisitQrDTO);
                }
                break;
            // 改预付
            case OrderLogConsts.ORDER_LOG_TYPE_UPDATE_CHANNEL_PREPAY_AMOUNT:
                ChangeRecordDTO changeRecordDTO = new ChangeRecordDTO();
                changeRecordDTO.setOrderId(omsBaseOperator.getOrderId());
                changeRecordDTO.setOperatorId(omsBaseOperator.getOperatorId());
                changeRecordDTO.setOperatorName(omsBaseOperator.getOperator());
                changeRecordDTO.setOperatorType(omsBaseOperator.getOperatorType());
                changeRecordDTO.setOperateTime(DateUtil.getNow());
                orderChangeRecordService.updateChangePrepayAmountRecord(changeRecordDTO);
                break;
        }
    }

    /**
     * 订单服务项修改记录保存
     *
     * @param orderLog
     * @param dbOrderWork
     * @param newOrderWork
     */
    private void recordServiceItemChange(OrderLog orderLog, OrderWork dbOrderWork, OrderWork newOrderWork) {

        if (Objects.isNull(orderLog) || Objects.isNull(dbOrderWork)) {
            return;
        }

        // 类型判断
        switch (orderLog.getType()) {
            // 修改、确认、改产品
            case OrderLogConsts.ORDER_LOG_TYPE_CONFIRM:
            case OrderLogConsts.ORDER_LOG_TYPE_UPDATE:
            case OrderLogConsts.ORDER_LOG_TYPE_MODIFY_PRODUCT:
                // 保存修改
                orderServiceItemChangeRecordService.updateOrderServiceItemChange(orderLog, dbOrderWork, newOrderWork, false);
                break;
            // 改服务项、改价格
            case OrderLogConsts.ORDER_LOG_TYPE_QUOTATION:
            case OrderLogConsts.ORDER_LOG_TYPE_SERVICEITEM:
            case OrderLogConsts.ORDER_LOG_TYPE_PLAT_UPDATE_PRICE:
            case OrderLogConsts.ORDER_LOG_TYPE_MASTER_CHANGE_PRICE:
                // 保存修改
                orderServiceItemChangeRecordService.updateOrderServiceItemChange(orderLog, dbOrderWork, newOrderWork, true);
                break;
            default:
                return;
        }

        // 保存修改

    }

    /**
     * 订单预约时间修改记录保存
     *
     * @param dutyTime
     * @param updateOpCount
     * @param omsBaseOperator
     */
    private void recordOrderDutyTimeChange(Date dutyTime, Date historyDutyTime, boolean updateOpCount, OmsBaseOperator omsBaseOperator) {
        if (Objects.isNull(omsBaseOperator)) {
            return;
        }

        if (Objects.isNull(dutyTime)) {
            return;
        }

        // 时间相等不处理
        if (Objects.equals(historyDutyTime, dutyTime)) {
            return;
        }


        ChangeDutyTimeDTO changeDutyTimeDTO = new ChangeDutyTimeDTO();
        changeDutyTimeDTO.setOrderId(omsBaseOperator.getOrderId());
        changeDutyTimeDTO.setDutyTime(dutyTime);
        changeDutyTimeDTO.setOperatorId(omsBaseOperator.getOperatorId());
        changeDutyTimeDTO.setOperatorName(omsBaseOperator.getOperator());
        changeDutyTimeDTO.setOperatorType(omsBaseOperator.getOperatorType());
        changeDutyTimeDTO.setUpdateOpCount(updateOpCount);

        orderChangeRecordService.updateChangeDutyTimeRecord(changeDutyTimeDTO);
    }

    /**
     * 订单派单修改记录保存
     *
     * @param autoDistribute
     * @param orderDistributeDTO
     * @auth xiewenbing
     */
    private void recordOrderDistributeChange(boolean autoDistribute, OrderDistributeDTO orderDistributeDTO) {
        if (Objects.isNull(orderDistributeDTO)) {
            return;
        }

        ChangeDistributeDTO changeDistributeDTO = new ChangeDistributeDTO();

        changeDistributeDTO.setOrderId(orderDistributeDTO.getOrderId());
        changeDistributeDTO.setDistributeTime(new Date());
        changeDistributeDTO.setOperatorId(orderDistributeDTO.getOperatorId());
        changeDistributeDTO.setOperatorName(orderDistributeDTO.getOperator());
        changeDistributeDTO.setOperatorType(orderDistributeDTO.getOperatorType());

        changeDistributeDTO.setDistributeType(autoDistribute ? OrderDistributeConsts.DISTRIBUTE_TYPE_AUTO : OrderDistributeConsts.DISTRIBUTE_TYPE_MANUAL);
        changeDistributeDTO.setDistributeRule(orderDistributeDTO.getDistributeRule());
        changeDistributeDTO.setDistributeWay(orderDistributeDTO.getDistributeWay());
        changeDistributeDTO.setDistributeEntry(orderDistributeDTO.getDistributeEntry());
        changeDistributeDTO.setDistributeGrid(orderDistributeDTO.getDistributeGrid());
        orderChangeRecordService.updateChangeDistributeRecord(changeDistributeDTO);
    }

    /**
     * 订单工程师形象照修改记录保存
     *
     * @param orderImageDTO
     */
    private void recordOrderMasterImageChange(OrderImageDTO orderImageDTO) {
        if (Objects.isNull(orderImageDTO)) {
            return;
        }

        logger.debug("#oms#updateMasterImage#{} 记录订单工程师形象照时间开始 orderImageDTO : {}", orderImageDTO.getOrderId(),
                orderImageDTO);
        ChangeMasterImageTimeDTO masterImageTimeDTO = new ChangeMasterImageTimeDTO();
        masterImageTimeDTO.setMasterImageTime(DateUtil.getNow());
        masterImageTimeDTO.setOperatorId(Long.valueOf(orderImageDTO.getMasterId()));
        masterImageTimeDTO.setOperatorName(orderImageDTO.getOperator());
        masterImageTimeDTO.setOperatorType(orderImageDTO.getOperatorType());
        masterImageTimeDTO.setOrderId(orderImageDTO.getOrderId());
        orderChangeRecordService.updateMasterImageTimeRecord(masterImageTimeDTO);
        logger.debug("#oms#updateMasterImage#{} 记录订单工程师形象照时间结束", orderImageDTO.getOrderId());
    }

    /**
     * 订单上门扫码
     *
     * @param masterVisitQrDTO
     */
    private void recordOrderVisitScanChange(MasterVisitQrDTO masterVisitQrDTO) {

        if (Objects.isNull(masterVisitQrDTO)) {
            return;
        }

        // 记录上门扫码时间
        logger.info("#ums#processMasterVisit 订单上门扫码时间记录开始");
        ChangeVisitScanTimeDTO visitScanTimeDTO = new ChangeVisitScanTimeDTO();
        visitScanTimeDTO.setOperatorId(masterVisitQrDTO.getOperatorId());
        visitScanTimeDTO.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_USER);
        visitScanTimeDTO.setOperatorName("微信用户");
        visitScanTimeDTO.setOrderId(masterVisitQrDTO.getOrderId());
        visitScanTimeDTO.setVisitScanTime(DateUtil.getNow());
        visitScanTimeDTO.setOpenId(masterVisitQrDTO.getOpenId());
        visitScanTimeDTO.setUnionId(masterVisitQrDTO.getUnionId());
        orderChangeRecordService.updateVisitScanTimeRecord(visitScanTimeDTO);
        logger.info("#ums#processMasterVisit 订单上门扫码时间记录结束");
    }

    /**
     * 非标信息
     *
     * @param omsOperator
     */
    private String orderNonstandardLog(OmsOperator omsOperator) {
        OrderNonstandardDTO orderNonstandardDTO = (OrderNonstandardDTO) omsOperator;
        StringBuilder sb = new StringBuilder();
        Integer imgFlag = orderNonstandardDTO.getImgFlag();
        List<OrderNonstandard> oldOrderNonstandardList = orderNonstandardDTO.getOldOrderNonstandardList();
        List<OrderNonstandard> newOrderNonstandardList = orderNonstandardDTO.getNewOrderNonstandardList();
        List<OrderNonstandard> addOrderNonstandardList = orderNonstandardDTO.getAddOrderNonstandardList();
        List<OrderNonstandard> delOrderNonstandardList = orderNonstandardDTO.getDelOrderNonstandardList();
        if (CollectionUtil.isNotNullOrEmpty(oldOrderNonstandardList) && CollectionUtil.isNotNullOrEmpty(newOrderNonstandardList)) {
            sb.append("修改：");
            for (int i = 0; i < oldOrderNonstandardList.size(); i++) {
                sb.append(String.format("\n信息名称：%s -> %s", oldOrderNonstandardList.get(i).getTitle(), newOrderNonstandardList.get(i).getTitle()));
                sb.append(String.format("\n信息内容：%s -> %s", oldOrderNonstandardList.get(i).getContent(), newOrderNonstandardList.get(i).getContent()));
            }
            if (imgFlag == 1) {
                sb.append("\n图片");
            }
            sb.append("\n");
        }
        if (CollectionUtil.isNotNullOrEmpty(addOrderNonstandardList)) {
            sb.append("新增：");
        }
        if (CollectionUtil.isNotNullOrEmpty(addOrderNonstandardList)) {
            for (OrderNonstandard orderNonstandard : addOrderNonstandardList) {
                sb.append(String.format("\n信息名称：%s ", orderNonstandard.getTitle()));
                sb.append(String.format("\n信息内容：%s ", orderNonstandard.getContent()));
            }
            if (imgFlag == 3) {
                sb.append("\n图片");
            }
            sb.append("\n");
        }
        if (CollectionUtil.isNotNullOrEmpty(delOrderNonstandardList)) {
            sb.append("删除：");
        }
        if (CollectionUtil.isNotNullOrEmpty(delOrderNonstandardList)) {
            for (OrderNonstandard orderNonstandard : delOrderNonstandardList) {
                sb.append(String.format("\n信息名称：%s ", orderNonstandard.getTitle()));
                sb.append(String.format("\n信息内容：%s ", orderNonstandard.getContent()));
            }
            if (imgFlag == 2) {
                sb.append("\n图片");
            }
        }
        return sb.toString();
    }

    /**
     * 通话记录
     *
     * @param omsOperator
     */
    private String callRecordLog(OmsOperator omsOperator) {
        CallRecordLogDTO callRecordLogDTO = (CallRecordLogDTO) omsOperator;
        logger.info("#oms#callRecordLog 记录操作log {}", JSONObject.toJSONString(callRecordLogDTO));
        StringBuilder sb = new StringBuilder();
        // 1 呼出：电话已呼出 ，2 呼通：被叫手机振铃 ，3 接听：被叫已接听电话
        if (Objects.equals(callRecordLogDTO.getStatus(), 1)) {
            sb.append("电话状态：呼出");
        } else if (Objects.equals(callRecordLogDTO.getStatus(), 2)) {
            sb.append("电话状态：呼通");
        } else if (Objects.equals(callRecordLogDTO.getStatus(), 3)) {
            sb.append("电话状态：接听");
        }
        sb.append("\n主叫：");
        sb.append(callRecordLogDTO.getCallType() == 1 ? "工程师" : "用户");
        sb.append("-");
        sb.append(MobileUtil.formatHideTel(callRecordLogDTO.getCallerNo()));
        sb.append("；被叫:");
        sb.append(callRecordLogDTO.getCalledType() == 1 ? "工程师" : "用户");
        sb.append("-");
        sb.append(MobileUtil.formatHideTel(callRecordLogDTO.getCalledNo()));
        if (callRecordLogDTO.getStatus() == 3) {
            // 接通记录通话时长
            sb.append("\n通话时间：");
            sb.append(DateUtil.toString(callRecordLogDTO.getStartTime(), DateUtil.FORMAT_DEFAULT));
            sb.append("-");
            sb.append(DateUtil.toString(callRecordLogDTO.getFinishTime(), DateUtil.FORMAT_DEFAULT));
            sb.append("；通话时长:");
            sb.append(callRecordLogDTO.getCallDuration());
        }

        return sb.toString();
    }

    private String unBindLog(OmsOperator omsOperator) {
        XnoUnBindDTO xnoUnBindDTO = (XnoUnBindDTO) omsOperator;
        Integer bindStatus = xnoUnBindDTO.getBindStatus();
        if (bindStatus == null) {
            return omsOperator.getOperatorLogRemark();
        }

        StringBuilder log = new StringBuilder();
        if (Objects.nonNull(xnoUnBindDTO.getUnBindMasterId())) {
            List unBindPhoneList = Lists.newArrayListWithExpectedSize(3);
            if (StringUtils.isNotBlank(xnoUnBindDTO.getUnBindTelephone1())) {
                unBindPhoneList.add(MobileUtil.formatHideTel(xnoUnBindDTO.getUnBindTelephone1()));
            }
            if (StringUtils.isNotBlank(xnoUnBindDTO.getUnBindTelephone2())) {
                unBindPhoneList.add(MobileUtil.formatHideTel(xnoUnBindDTO.getUnBindTelephone2()));
            }
            if (StringUtils.isNotBlank(xnoUnBindDTO.getUnBindTelephone3())) {
                unBindPhoneList.add(MobileUtil.formatHideTel(xnoUnBindDTO.getUnBindTelephone3()));
            }
            if (CollectionUtils.isNotEmpty(unBindPhoneList)) {
                log.append("[小号解绑成功]解绑用户电话：").append(String.join("，", unBindPhoneList));
            }
        } else {
            log.append("[小号解绑：绑定信息不存在，不需要解绑]");
        }
        return log.toString();
    }

    /**
     * 小号绑定日志
     *
     * @param omsOperator
     */
    private String bindLog(OrderWork dbOrderWork, OmsOperator omsOperator) {
        XnoBindDTO xnoBindDTO = (XnoBindDTO) omsOperator;

        // 绑定失败直接返回
        if (StringUtils.isNotBlank(xnoBindDTO.getFailMessage())) {
            return xnoBindDTO.getFailMessage();
        }

        StringBuilder log = new StringBuilder();
        log.append("\n[绑定信息]\n");
        if (StringUtils.isNotBlank(omsOperator.getOperatorLogRemark())) {
            log.append(omsOperator.getOperatorLogRemark());
        }

        //
        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(dbOrderWork.getOrderId(), dbOrderWork.getWorkId());
        // todo fubiao
        logger.info("bindLog#getEngineerDetailById 入参t [{}]", orderWork.getMasterId());
        ResponseDTO<ForeignEngineerDetailInfoDRO> cacheEngineerByEngineerId = engineerListRemoteService.getEngineerDetailById(orderWork.getMasterId());
        logger.info("bindLog#getEngineerDetailById 出参 [{}]", JSON.toJSONString(cacheEngineerByEngineerId));
        ForeignEngineerDetailInfoDRO baseEngineerDRO = cacheEngineerByEngineerId.getData();
        if (!cacheEngineerByEngineerId.isSuccess() || baseEngineerDRO == null) {
            return log.toString();
        }

        OrderDetail orderDetail = orderDetailService.findOrderDetailByKeySrcMaster(dbOrderWork.getOrderId());
        this.processBindLog(log, orderDetail, baseEngineerDRO.getMobile(), orderWork);
        return log.toString();
    }

    /**
     * 临时小号绑定日志
     *
     * @param omsOperator
     */
    private String tempBindLog(OrderWork dbOrderWork, OmsOperator omsOperator) {
        TempXnoBindDTO tempXnoBindDTO = (TempXnoBindDTO) omsOperator;

        // 绑定失败直接返回
        if (StringUtils.isNotBlank(tempXnoBindDTO.getFailMessage())) {
            return "小号绑定失败：" + tempXnoBindDTO.getFailMessage();
        }

        StringBuilder log = new StringBuilder("绑定小号成功\n");
        log.append(String.format("绑定信息：用户电话：%s - 小号：%s - %s电话：%s - 绑定成功",
                MobileUtil.formatHideTel(tempXnoBindDTO.getUserTelephone()),
                tempXnoBindDTO.getXnoTelephone(),
                omsOperator.getOperator(),
                MobileUtil.formatHideTel(tempXnoBindDTO.getBindTelephone())));
        return log.toString();
    }

    /**
     * 临时小号解除绑定日志
     *
     * @param omsOperator
     */
    private String tempUnBindLog(OrderWork dbOrderWork, OmsOperator omsOperator) {
        TempXnoUnBindDTO tempXnoUnBindDTO = (TempXnoUnBindDTO) omsOperator;
        StringBuilder log = new StringBuilder("[临时小号解绑成功]\n");
        log.append(String.format("解绑用户电话：%s - 解绑%s电话：%s",
                MobileUtil.formatHideTel(tempXnoUnBindDTO.getUserTelephone()),
                tempXnoUnBindDTO.getBindOperator(),
                MobileUtil.formatHideTel(tempXnoUnBindDTO.getBindTelephone())));
        return log.toString();
    }

    private boolean processBindLog(StringBuilder log, OrderDetail orderDetail, String masterTelephone, OrderWork orderWork) {
        // 查询小号
        String telephone = orderDetail.getTelephone();
        String telephone2 = orderDetail.getTelephone2();
        String telephone3 = orderDetail.getTelephone3();
        // 绑定标志
        boolean bindFlag = false;
        if (StringUtils.isNotBlank(telephone)) {
            ZsXnoBindVO zsXnoBindVO = orderXnoBindService.queryXNO(masterTelephone, telephone, orderWork);
            if (zsXnoBindVO == null) {
                log.append("切换失败");
            } else {
                bindFlag = true;
                log.append(String.format("\n用户电话：%s - 小号：%s - 工程师电话：%s", MobileUtil.formatHideTel(telephone), zsXnoBindVO.getXno(), MobileUtil.formatHideTel(masterTelephone))).append(" - 绑定成功");
            }
        }
        if (StringUtils.isNotBlank(telephone2)) {
            ZsXnoBindVO zsXnoBindVO2 = orderXnoBindService.queryXNO(masterTelephone, telephone2, orderWork);
            if (zsXnoBindVO2 == null) {
                log.append("切换失败");
            } else {
                bindFlag = true;
                log.append(String.format("\n用户电话：%s - 小号：%s - 工程师电话：%s", MobileUtil.formatHideTel(telephone2), zsXnoBindVO2.getXno(), MobileUtil.formatHideTel(masterTelephone))).append(" - 绑定成功");
            }
        }
        if (StringUtils.isNotBlank(telephone3)) {
            ZsXnoBindVO zsXnoBindVO3 = orderXnoBindService.queryXNO(masterTelephone, telephone3, orderWork);
            if (zsXnoBindVO3 == null) {
                log.append("切换失败");
            } else {
                bindFlag = true;
                log.append(String.format("\n用户电话：%s - 小号：%s - 工程师电话：%s", MobileUtil.formatHideTel(telephone3), zsXnoBindVO3.getXno(), MobileUtil.formatHideTel(masterTelephone))).append(" - 绑定成功");
            }
        }
        return bindFlag;
    }

    /**
     * 快递信息操作日志记录
     *
     * @param omsOperator
     */
    private String updateOrderPostLog(OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();
        OrderPostListDTO orderPostListDTO = (OrderPostListDTO) omsOperator;
        List<OrderPost> postList = orderPostListDTO.getPostList();

        if (CollectionUtils.isNotEmpty(postList)) {
            log.append("快递信息:\n");
            postList.forEach(orderPost -> {
                log.append(String.format("快递单号:%s 快递公司:%s 类型:%s 快递备注:%s \n",
                        orderPost.getExpressCode(),
                        orderPost.getExpressCompany(),
                        OrderPostConsts.getExpressItemTypeName(orderPost.getItemType()),
                        StringUtils.defaultString(orderPost.getRemark(), ""))
                );

            });
        }

        if (StringUtil.isNotBlank(orderPostListDTO.getOperatorRemark())) {
            log.append(String.format("操作备注:%s \n", orderPostListDTO.getOperatorRemark()));
        }
        return log.toString();
    }

    /**
     * 师傅分润信息
     *
     * @param omsOperator
     */
    private String masterShare(OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();
        MasterSharingDTO masterSharingDTO = (MasterSharingDTO) omsOperator;

        for (SharingInfo sharingInfo : masterSharingDTO.getSharingInfoList()) {
            if (Objects.equals(sharingInfo.getType(), OrderConsts.ORDER_MASTER_TYPE_MAIN)) {
                log.append("主工程师-");
            } else {
                log.append("从工程师-");
            }
            log.append(sharingInfo.getMasterName()).append("-");
            log.append(NumberUtil.divAndToPercent(sharingInfo.getShareRate(), 10000)).append("；\n");

        }
        return log.toString();
    }

    /**
     * 新机配件信息操作日志记录
     *
     * @param omsOperator
     * @return java.lang.String
     * @author wangxiaokun
     */
    private String updateOrderNewMachinePartLog(OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();
        OrderNewMachinePartListDTO dto = (OrderNewMachinePartListDTO) omsOperator;
        // 保存的新机物流
        List<OrderPost> postList = dto.getOrderPostList();
        // 保存的厂商配件物流
        List<FactoryNewOrderPartDIO> partDIOS = dto.getPartDIOS();

        if (CollectionUtil.isNotNullOrEmpty(postList)) {
            log.append("新增：新机物流信息：\n");
            postList.forEach(orderPost -> {
                log.append(String.format("物流单号：%s、物流公司：%s、快递类型：%s、备注：%s；\n",
                        orderPost.getExpressCode(),
                        orderPost.getExpressCompany(),
                        OrderPostConsts.getExpressItemTypeName(orderPost.getItemType()),
                        StringUtils.defaultString(orderPost.getRemark(), ""))
                );
            });
        } else if (CollectionUtil.isNotNullOrEmpty(dto.getOldOrderPostList()) && CollectionUtil.isNullOrEmpty(postList)) {
            log.append("删除：新机物流信息\n");
        }
        if (CollectionUtil.isNotNullOrEmpty(partDIOS)) {
            log.append("新增：配件-厂商配件：\n");
            partDIOS.forEach(part -> {
                log.append(String.format("配件名称：%s、数量：%s；\n物流单号：%s、快递公司：%s、邮寄对象：%s;\n",
                        part.getPartFullName(), part.getNumber(), part.getExpressCode(), part.getExpressCompany(),
                        OrderFactoryPartConsts.getPostAddressTypeName(part.getPostTarget())));
            });
        } else if (CollectionUtil.isNotNullOrEmpty(dto.getNewPartVOS()) && CollectionUtil.isNullOrEmpty(partDIOS)) {
            log.append("删除：配件-厂商配件\n");
        }

        if (StringUtil.isNotBlank(dto.getOperatorRemark())) {
            log.append(String.format("操作备注:%s \n", dto.getOperatorRemark()));
        }
        return log.toString();
    }

    /**
     * 不认领订单
     *
     * @param omsOperator
     * @return java.lang.String
     * @author wangxiaokun
     */
    private String nonClaimOrdertLog(OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();
        NonClaimOrderDTO dto = (NonClaimOrderDTO) omsOperator;
        log.append("用户（userId：").append(dto.getOperatorId()).append("）确认不是自己订单");
        return log.toString();
    }

    /**
     * 更改分配
     *
     * @param omsOperator
     * @return java.lang.String
     * @author wangxiaokun
     */
    private String changeAssignmentOrdertLog(OmsOperator omsOperator) {
        StringBuilder log = new StringBuilder();
        OrderWorkGrabDTO dto = (OrderWorkGrabDTO) omsOperator;
        if (Objects.equals(dto.getGrabType(), GlobalConsts.YES)) {
            if (Objects.equals(dto.getGrabWay(), GlobalConsts.YES)) {
                log.append("派单->无网格抢单");
            } else {
                log.append("派单->抢单");
            }
        } else {
            if (Objects.equals(dto.getGrabWay(), GlobalConsts.YES)) {
                log.append("无网格抢单->派单");
            } else {
                log.append("抢单->派单");
            }
        }
        return log.toString();
    }

    /**
     * 处理返修订单log的操作
     *
     * @param newOrderLog  工单日志
     * @param newOrderWork
     */
    private void processReworkOrderLog(OrderLog newOrderLog, OrderWork newOrderWork) {
        if (Objects.isNull(newOrderWork)) {
            return;
        }

        if (!Objects.equals(newOrderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_INPUT) || !Objects.equals(newOrderWork.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
            return;
        }

        // 查询原单
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(newOrderWork.getReworkId(), newOrderWork.getReworkId());
        if (Objects.isNull(orderWork)) {
            logger.info("没有获取到原返修单 orderId【】, reworkId【】", newOrderWork.getReworkId(), newOrderWork.getReworkId());
            return;
        }

        OrderLog orderLog = new OrderLog();
        orderLog.setOrderId(orderWork.getOrderId());
        orderLog.setWorkId(orderWork.getWorkId());
        orderLog.setBeforeStatus(orderWork.getStatus());
        orderLog.setBeforeStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setBeforeResultStatus(orderWork.getResultStatus());
        orderLog.setBeforeResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));
        orderLog.setAfterStatus(orderLog.getBeforeStatus());
        orderLog.setAfterStatusName(orderLog.getBeforeStatusName());
        orderLog.setAfterResultStatus(orderLog.getBeforeResultStatus());
        orderLog.setAfterResultStatusName(orderLog.getBeforeResultStatusName());
        orderLog.setOperator(newOrderLog.getOperator());
        orderLog.setOperatorId(newOrderLog.getOperatorId());
        orderLog.setOperatorType(newOrderLog.getOperatorType());
        orderLog.setOperatorTypeName(newOrderLog.getOperatorTypeName());

        // 内容
        orderLog.setContent(newOrderLog.getContent());
        orderLog.setType(OrderLogConsts.ORDER_LOG_TYPE_INPUT_REWORK);
        orderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(OrderLogConsts.ORDER_LOG_TYPE_INPUT_REWORK));

        orderLogBService.save(orderLog);
    }


    /**
     * 处理退款订单log的操作
     *
     * @param newOrderLog 工单日志
     * @param dbOrderWork
     */
    private void processRefundOrderLog(OrderLog newOrderLog, OrderWork dbOrderWork) {
        logger.info("processRefundOrderLog newOrderLog=[{}], dbOrderWork=[{}]", newOrderLog, dbOrderWork);
        if (Objects.isNull(dbOrderWork)) {
            return;
        }

        if (!Objects.equals(newOrderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_REFUND)) {
            return;
        }

        // 查询原单
        OrderWork orderWork = dbOrderWork;
        if (Objects.equals(dbOrderWork.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
            orderWork = orderWorkService.findOrderWorkByKey(dbOrderWork.getOriginalId(), dbOrderWork.getOriginalId());
        }

        if (Objects.isNull(orderWork)) {
            logger.info("没有获取到原退款单 orderId【】, refundWorkId【】,refundTargetWorkId【】", dbOrderWork.getOrderId(), dbOrderWork.getRefundWorkId(), dbOrderWork.getRefundTargetWorkId());
            return;
        }

        OrderLog orderLog = new OrderLog();
        orderLog.setOrderId(orderWork.getOrderId());
        orderLog.setWorkId(orderWork.getWorkId());
        orderLog.setBeforeStatus(orderWork.getStatus());
        orderLog.setBeforeStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setBeforeResultStatus(orderWork.getResultStatus());
        orderLog.setBeforeResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));
        orderLog.setAfterStatus(orderLog.getBeforeStatus());
        orderLog.setAfterStatusName(orderLog.getBeforeStatusName());
        orderLog.setAfterResultStatus(orderLog.getBeforeResultStatus());
        orderLog.setAfterResultStatusName(orderLog.getBeforeResultStatusName());
        orderLog.setOperator(newOrderLog.getOperator());
        orderLog.setOperatorId(newOrderLog.getOperatorId());
        orderLog.setOperatorType(newOrderLog.getOperatorType());
        orderLog.setOperatorTypeName(newOrderLog.getOperatorTypeName());

        // 内容
        orderLog.setContent(newOrderLog.getContent());
        orderLog.setType(OrderLogConsts.ORDER_LOG_TYPE_INPUT_REFUND);
        orderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(OrderLogConsts.ORDER_LOG_TYPE_INPUT_REFUND));

        orderLogBService.save(orderLog);
    }

    /**
     * 处理赔偿订单log的操作
     *
     * @param newOrderLog
     * @param dbOrderWork
     */
    private void processCompensateOrderLog(OrderLog newOrderLog, OrderWork dbOrderWork) {
        if (Objects.isNull(dbOrderWork)) {
            return;
        }

        // 原单只保存新建赔偿单日志
        if (!Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_COMPENSATE, newOrderLog.getType())) {
            return;
        }

        logger.info("processCompensateOrderLog newOrderLog=[{}] dbOrderWork=[{}]", newOrderLog, dbOrderWork);

        // 查询原单
        OrderWork originalOrderWork = dbOrderWork;
        if (Objects.equals(dbOrderWork.getType(), OrderConsts.ORDER_TYPE_COMPENSATE)) {
            originalOrderWork = orderWorkService.findOrderWorkByKey(dbOrderWork.getOriginalId(), dbOrderWork.getOriginalId());
        }

        if (Objects.isNull(originalOrderWork)) {
            logger.info("没有获取到原单信息", dbOrderWork.getOriginalId());
            return;
        }

        OrderLog orderLog = new OrderLog();
        orderLog.setOrderId(originalOrderWork.getOrderId());
        orderLog.setWorkId(originalOrderWork.getWorkId());
        orderLog.setBeforeStatus(originalOrderWork.getStatus());
        orderLog.setBeforeStatusName(OrderStatusConsts.getWorkStatusName(originalOrderWork.getStatus()));
        orderLog.setBeforeResultStatus(originalOrderWork.getResultStatus());
        orderLog.setBeforeResultStatusName(OrderStatusConsts.getWorkResultStatusName(originalOrderWork.getResultStatus()));
        orderLog.setAfterStatus(orderLog.getBeforeStatus());
        orderLog.setAfterStatusName(orderLog.getBeforeStatusName());
        orderLog.setAfterResultStatus(orderLog.getBeforeResultStatus());
        orderLog.setAfterResultStatusName(orderLog.getBeforeResultStatusName());
        orderLog.setOperator(newOrderLog.getOperator());
        orderLog.setOperatorId(newOrderLog.getOperatorId());
        orderLog.setOperatorType(newOrderLog.getOperatorType());
        orderLog.setOperatorTypeName(newOrderLog.getOperatorTypeName());

        // 内容
        orderLog.setContent(newOrderLog.getContent());
        orderLog.setType(OrderLogConsts.ORDER_LOG_TYPE_INPUT_COMPENSATE);
        orderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(OrderLogConsts.ORDER_LOG_TYPE_INPUT_COMPENSATE));

        orderLogBService.save(orderLog);
    }

    /**
     * 预约失败log
     *
     * @param orderLog
     * @param dbOrderWork
     * @param newOrderWork
     */
    private void processDutyFailOrderLog(OrderLog orderLog, OrderWork dbOrderWork, OrderWork newOrderWork) {
        logger.info("processDutyFailOrderLog newOrderLog={},  newOrderWork={}", orderLog, newOrderWork);
        if (Objects.isNull(newOrderWork) || Objects.isNull(dbOrderWork)) {
            return;
        }

        boolean isUpdateOrder = Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_UPDATE) || Objects.equals(orderLog.getType(), OrderLogConsts.ORDER_LOG_TYPE_CONFIRM);
        if (!isUpdateOrder) {
            return;
        }

        // 预约失败
        if (!Objects.equals(OrderDutyConsts.DUTY_STATUS_FAIL, newOrderWork.getDutyStatus())) {
            return;
        }

        OrderLog newOrderLog = new OrderLog();
        newOrderLog.setOrderId(orderLog.getOrderId());
        newOrderLog.setWorkId(orderLog.getWorkId());
        newOrderLog.setBeforeStatus(orderLog.getBeforeStatus());
        newOrderLog.setBeforeStatusName(orderLog.getBeforeStatusName());
        newOrderLog.setBeforeResultStatus(orderLog.getBeforeResultStatus());
        newOrderLog.setBeforeResultStatusName(orderLog.getBeforeResultStatusName());
        newOrderLog.setAfterStatus(orderLog.getBeforeStatus());
        newOrderLog.setAfterStatusName(orderLog.getBeforeStatusName());
        newOrderLog.setAfterResultStatus(orderLog.getBeforeResultStatus());
        newOrderLog.setAfterResultStatusName(orderLog.getBeforeResultStatusName());
        newOrderLog.setOperator(orderLog.getOperator());
        newOrderLog.setOperatorId(orderLog.getOperatorId());
        newOrderLog.setOperatorType(orderLog.getOperatorType());
        newOrderLog.setOperatorTypeName(orderLog.getOperatorTypeName());

        // 内容
        newOrderLog.setContent(String.format("预约失败：下次联系时间：%s，失败原因：%s",
                Objects.isNull(newOrderWork.getNextContactTime()) ? "" : DateUtil.toString(newOrderWork.getNextContactTime(), DateUtil.FORMAT_DATETIME),
                Objects.isNull(newOrderWork.getDutyFailCode()) ? "" : OrderDutyConsts.getDutyFailedReasonName(newOrderWork.getDutyFailCode())));
        newOrderLog.setType(OrderLogConsts.ORDER_LOG_TYPE_UPDATE_DUTY_FAIL);
        newOrderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(OrderLogConsts.ORDER_LOG_TYPE_UPDATE_DUTY_FAIL));

        orderLogBService.save(newOrderLog);
    }

    /**
     * 取消
     *
     * @param omsOperator
     * @return
     */
    String orderWorkTagLog(OrderWork dbOrderWork, OmsOperator omsOperator) {
        OrderWorkTagDTO orderWorkTagDTO = (OrderWorkTagDTO) omsOperator;
        StringBuilder log = new StringBuilder();

        List<OrderTag> tags = orderWorkTagDTO.getTags();
        log.append("标记：");
        if (CollectionUtils.isNotEmpty(tags)) {
            tags.forEach(detail -> {
                log.append(",");
                log.append(detail.getTagName());
            });
        }

        log.append("；备注：").append(StringUtils.defaultString(orderWorkTagDTO.getRemark()));
        return log.toString();
    }

    /**
     * 取消审核
     *
     * @param omsOperator
     * @return
     */
    String cancelReviewLog(OmsOperator omsOperator) {
        CancelConfirmDTO cancelConfirmDTO = (CancelConfirmDTO) omsOperator;
        if (Objects.equals(cancelConfirmDTO.getType(), com.zmn.consts.GlobalConsts.YES)) {
            return "用户同意继续维修";
        }
        if (Objects.equals(cancelConfirmDTO.getType(), com.zmn.consts.GlobalConsts.NO)) {
            return "工程师同意取消";
        }
        return "";
    }

    /**
     * 添加订单验收
     *
     * @param omsOperator
     * @return
     */
    String addAcceptance(OmsOperator omsOperator) {
        OrderWorkAcceptanceDTO dto = (OrderWorkAcceptanceDTO) omsOperator;
        if (Objects.equals(dto.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_PAYMENT_CONFIRM)
                || Objects.equals(dto.getAcceptanceType(), OrderConsts.ORDER_ACCEPTANCE_TYPE_PROGRESS_CONFIRM)) {
            return "工程师发起收款确认";
        } else {
            return "工程师发起服务验收";
        }
    }

    /**
     * 用户确认故障现象
     *
     * @param omsOperator
     * @return
     */
    String userConfirmFaultPhen(OmsOperator omsOperator) {
        ConfirmFaultInfoDIO dto = (ConfirmFaultInfoDIO) omsOperator;

        StringBuilder sb = new StringBuilder();
        sb.append("用户确认故障现象：");
        String phenNameStr = dto.getPhenList().stream().map(FaultPhenoDIO::getPhenName).collect(Collectors.joining("、"));
        sb.append(phenNameStr);

        return sb.toString();
    }

    /**
     * 开始检修
     *
     * @param omsOperator
     * @return
     */
    String startCheck(OmsOperator omsOperator) {
        return "工程师开始检修";
    }

    /**
     * 生成检修单
     *
     * @param omsOperator
     * @return
     */
    String submitCheckReport(OmsOperator omsOperator) {
        CheckReportDIO dto = (CheckReportDIO) omsOperator;

        List<OrderMaintainItemDIO> maintainItemList = dto.getMaintainItemList();

        Long abnormalCount = maintainItemList.stream().filter(item -> !Optional.ofNullable(item.isStatus()).orElse(false)).count();

        StringBuilder sb = new StringBuilder();
        if (Objects.equals(GlobalConsts.YES, dto.getEditStatus())) {
            sb.append("重新");
        }
        sb.append("生成检修单：共检测");
        sb.append(maintainItemList.size()).append("项，");
        sb.append(abnormalCount).append("项异常，");
        sb.append("故障详解：").append(dto.getFaultNameStr());

        return sb.toString();
    }

    /**
     * 处理检修单
     *
     * @param omsOperator
     * @return
     */
    String processCheckReport(OmsOperator omsOperator) {
        ConfirmCheckReportDIO dto = (ConfirmCheckReportDIO) omsOperator;
        StringBuilder sb = new StringBuilder();
        if (Objects.equals(GlobalConsts.YES, dto.getEditStatus())) {
            sb.append("确认检修报告，重新");
        }
        if (Objects.equals(dto.getIsSendCheckReportToUser(), GlobalConsts.YES)) {
            sb.append("发送给用户");
        } else {
            sb.append("给用户讲解");
        }
        return sb.toString();
    }

    /**
     * 用户确认故障现象
     *
     * @param omsOperator
     * @return
     */
    String agreeRepairResultWithCaptcha(OmsOperator omsOperator) {
        ConfirmRepairDIO confirmRepairDIO = (ConfirmRepairDIO) omsOperator;
        if (Objects.equals(confirmRepairDIO.getResult(), GlobalConsts.YES)) {
            return "用户同意维修-验证码验证";
        } else {
            return "不同意维修";
        }
    }

    /**
     * 用户确认故障现象
     *
     * @param omsOperator
     * @return
     */
    String agreeRepairResult(OmsOperator omsOperator) {
        ConfirmRepairDIO dto = (ConfirmRepairDIO) omsOperator;
        if (Objects.equals(dto.getResult(), GlobalConsts.YES)) {
            return "同意维修";
        } else {
            return "不同意维修";
        }
    }

    /**
     * 用户领取工程师优惠
     *
     * @param omsOperator
     * @return
     */
    String useEngineerDiscount(OmsOperator omsOperator) {
        EngineerDiscountDIO dto = (EngineerDiscountDIO) omsOperator;
        StringBuilder sb = new StringBuilder();
        sb.append("用户领取工程师优惠，优惠ID：").append(dto.getPromId());
        return sb.toString();
    }

    /**
     * 工程师使用次卡（权益卡）
     *
     * @param omsOperator
     * @return
     */
    String useTimesCard(OmsOperator omsOperator) {
        UseTimesCoupBO bo = (UseTimesCoupBO) omsOperator;
        return bo.getLogContent();
    }

    /**
     * 催单
     *
     * @return
     */
    String reminder(OmsOperator omsOperator) {
        RemindDTO remindDTO = (RemindDTO) omsOperator;
        StringBuilder log = new StringBuilder("手动触发机器人催单");
        log.append("\n备注：").append(StringUtils.defaultString(remindDTO.getRemark()));
        return log.toString();
    }

    /**
     * 一键提醒
     *
     * @return
     */
    String oneClickReminder(OrderWork dbOrderWork, OmsOperator omsOperator) {
        RemindDTO remindDTO = (RemindDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        log.append("提醒类型：联系\n");
        log.append(String.format("联系场景：%s\n", remindDTO.getSceneName()));
        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(dbOrderWork.getOrderId(), dbOrderWork.getWorkId());
        // todo fubiao
        logger.info("oneClickReminder#getEngineerDetailById 入参 [{}]", orderWork.getMasterId());
        ResponseDTO<ForeignEngineerDetailInfoDRO> cacheEngineerByEngineerId = engineerListRemoteService.getEngineerDetailById(orderWork.getMasterId());
        logger.info("oneClickReminder#getEngineerDetailById 出参 [{}]", JSON.toJSONString(cacheEngineerByEngineerId));
        ForeignEngineerDetailInfoDRO baseEngineerDRO = cacheEngineerByEngineerId.getData();
        if (!cacheEngineerByEngineerId.isSuccess() || baseEngineerDRO == null) {
            return log.toString();
        }
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(dbOrderWork.getOrderId());
        StringBuilder xnoBindLog = new StringBuilder();
        if (this.processBindLog(xnoBindLog, orderDetail, baseEngineerDRO.getMobile(), orderWork)) {
            log.append("绑定信息：");
            log.append(xnoBindLog);
        } else {
            log.append("联系-绑定小号失败\n");
        }
        if (StringUtil.isNotBlank(remindDTO.getRemark())) {
            log.append("\n备注：").append(remindDTO.getRemark());
        }
        return log.toString();
    }

    private String refundDifference(OmsOperator omsOperator) {
        RefundDifferenceDTO refundDifferenceDTO = (RefundDifferenceDTO) omsOperator;
        StringBuilder log = new StringBuilder();
        log.append("退款金额：").append(MoneyUtil.parseToYuanStr(refundDifferenceDTO.getRefundDifferenceAmount())).append("\n");
        log.append("退款方式：原路退款\n");

        return log.toString();
    }
}
